Alan Zimmerman pushed to branch wip/az/ghc-cpp at Glasgow Haskell Compiler / GHC
Commits:
-
b70fb2a2
by Alan Zimmerman at 2025-06-08T16:16:16+02:00
10 changed files:
- compiler/GHC/Parser/Errors/Ppr.hs
- compiler/GHC/Parser/Errors/Types.hs
- compiler/GHC/Parser/Lexer.x
- compiler/GHC/Parser/PreProcess.hs
- compiler/GHC/Parser/PreProcess/State.hs
- compiler/GHC/Types/Error/Codes.hs
- + testsuite/tests/ghc-cpp/GhcCpp02.stderr
- testsuite/tests/ghc-cpp/all.T
- utils/check-cpp/PreProcess.hs
- utils/check-cpp/State.hs
Changes:
... | ... | @@ -573,6 +573,9 @@ instance Diagnostic PsMessage where |
573 | 573 | -> mkSimpleDecorated $
|
574 | 574 | text "The" <+> quotes (text "pattern") <+> "namespace specifier is deprecated."
|
575 | 575 | |
576 | + PsErrGhcCpp content
|
|
577 | + -> mkSimpleDecorated content
|
|
578 | + |
|
576 | 579 | diagnosticReason = \case
|
577 | 580 | PsUnknownMessage m -> diagnosticReason m
|
578 | 581 | PsHeaderMessage m -> psHeaderMessageReason m
|
... | ... | @@ -695,6 +698,7 @@ instance Diagnostic PsMessage where |
695 | 698 | PsErrSpecExprMultipleTypeAscription{} -> ErrorWithoutFlag
|
696 | 699 | PsWarnSpecMultipleTypeAscription{} -> WarningWithFlag Opt_WarnDeprecatedPragmas
|
697 | 700 | PsWarnPatternNamespaceSpecifier{} -> WarningWithFlag Opt_WarnPatternNamespaceSpecifier
|
701 | + PsErrGhcCpp{} -> ErrorWithoutFlag -- AZ: Is this correct?
|
|
698 | 702 | |
699 | 703 | diagnosticHints = \case
|
700 | 704 | PsUnknownMessage m -> diagnosticHints m
|
... | ... | @@ -873,6 +877,7 @@ instance Diagnostic PsMessage where |
873 | 877 | let info = text "and replace" <+> quotes (text "pattern")
|
874 | 878 | <+> text "with" <+> quotes (text "data") <> "."
|
875 | 879 | in [useExtensionInOrderTo info LangExt.ExplicitNamespaces]
|
880 | + PsErrGhcCpp{} -> noHints
|
|
876 | 881 | |
877 | 882 | diagnosticCode = constructorCode @GHC
|
878 | 883 |
... | ... | @@ -515,6 +515,9 @@ data PsMessage |
515 | 515 | | PsWarnPatternNamespaceSpecifier
|
516 | 516 | !Bool -- ^ Is ExplicitNamespaces on?
|
517 | 517 | |
518 | + -- | An error originating from processing a GHC_CPP directive
|
|
519 | + | PsErrGhcCpp !SDoc
|
|
520 | + |
|
518 | 521 | deriving Generic
|
519 | 522 | |
520 | 523 | -- | Extra details about a parse error, which helps
|
... | ... | @@ -335,9 +335,9 @@ $unigraphic / { isSmartQuote } { smart_quote_error } |
335 | 335 | |
336 | 336 | ^\# \ * $idchar+ .*\n / { ifExtensionGhcCppNotComment } { cppSkip } -- No leading space, otherwise clashes with OverloadedLabels
|
337 | 337 | |
338 | - ^\# pragma .* \n / { ifExtensionGhcCppNotComment } { cppSkip } -- GCC 3.3 CPP generated, apparently
|
|
339 | - ^\# \! .* \n / { ifExtensionGhcCppNotComment } { cppSkip } -- #!, for scripts -- gcc
|
|
340 | - ^\ \# \! .* \n / { ifExtensionGhcCppNotComment } { cppSkip } -- #!, for scripts -- clang; See #6132
|
|
338 | + ^\# pragma .* \n / { ifExtensionGhcCppNotComment } { cppSkip } -- GCC 3.3 CPP generated, apparently
|
|
339 | + ^\# \! .* \n / { ifExtensionGhcCppNotComment } { cppSkip } -- #!, for scripts -- gcc
|
|
340 | + ^\ \# \! .* \n / { ifExtensionGhcCppNotComment } { cppSkip } -- #!, for scripts -- clang; See #6132
|
|
341 | 341 | |
342 | 342 | ^\# pragma .* \n ; -- GCC 3.3 CPP generated, apparently
|
343 | 343 | ^\# \! .* \n ; -- #!, for scripts -- gcc
|
... | ... | @@ -351,7 +351,7 @@ $unigraphic / { isSmartQuote } { smart_quote_error } |
351 | 351 | <skipping> {
|
352 | 352 | -- Ghc CPP symbols
|
353 | 353 | ^\# \ * @cppkeyword .* \n { cppToken cpp_prag }
|
354 | - ^.*\n { cppSkip }
|
|
354 | + ^.*\n { cppSkip }
|
|
355 | 355 | }
|
356 | 356 | |
357 | 357 | -- after a layout keyword (let, where, do, of), we begin a new layout
|
... | ... | @@ -14,6 +14,7 @@ module GHC.Parser.PreProcess ( |
14 | 14 | ) where
|
15 | 15 | |
16 | 16 | import Data.List (intercalate, sortBy)
|
17 | +import Data.Maybe (fromMaybe, listToMaybe)
|
|
17 | 18 | import Data.Map qualified as Map
|
18 | 19 | import Debug.Trace (trace)
|
19 | 20 | import GHC.Data.FastString
|
... | ... | @@ -30,8 +31,10 @@ import GHC.Parser.PreProcess.ParserM qualified as PM |
30 | 31 | import GHC.Parser.PreProcess.State
|
31 | 32 | import GHC.Prelude
|
32 | 33 | import GHC.Types.SrcLoc
|
33 | -import GHC.Utils.Outputable (SDoc, text)
|
|
34 | +import GHC.Utils.Error
|
|
35 | +import GHC.Utils.Outputable (text)
|
|
34 | 36 | import GHC.Utils.Panic.Plain (panic)
|
37 | +import GHC.Parser.Errors.Types (PsMessage(PsErrGhcCpp))
|
|
35 | 38 | |
36 | 39 | -- ---------------------------------------------------------------------
|
37 | 40 | |
... | ... | @@ -212,7 +215,7 @@ ppLexer queueComments cont = |
212 | 215 | pushContinuation tk
|
213 | 216 | contIgnoreTok tk
|
214 | 217 | else do
|
215 | - mdump <- processCppToks s
|
|
218 | + mdump <- processCppToks tk
|
|
216 | 219 | case mdump of
|
217 | 220 | Just dump ->
|
218 | 221 | -- We have a dump of the state, put it into an ignored token
|
... | ... | @@ -241,25 +244,25 @@ ppLexer queueComments cont = |
241 | 244 | |
242 | 245 | -- ---------------------------------------------------------------------
|
243 | 246 | |
244 | -processCppToks :: FastString -> PP (Maybe String)
|
|
247 | +processCppToks :: Located Lexer.Token -> PP (Maybe String)
|
|
245 | 248 | processCppToks fs = do
|
246 | 249 | let
|
247 | 250 | get (L _ (ITcpp False s _)) = unpackFS s
|
248 | 251 | get (L _ (ITcpp True s _)) = init $ unpackFS s
|
249 | - get _ = error "should not"
|
|
252 | + get _ = panic "Should be ITcpp"
|
|
250 | 253 | -- Combine any prior continuation tokens
|
251 | 254 | cs <- popContinuation
|
252 | - processCpp (reverse $ unpackFS fs : map get cs)
|
|
255 | + let loc = combineLocs fs (fromMaybe fs (listToMaybe cs))
|
|
256 | + processCpp loc (concat $ reverse $ map get (fs:cs))
|
|
253 | 257 | |
254 | -processCpp :: [String] -> PP (Maybe String)
|
|
255 | -processCpp ss = do
|
|
256 | - let s = concat ss
|
|
258 | +processCpp :: SrcSpan -> String -> PP (Maybe String)
|
|
259 | +processCpp loc s = do
|
|
257 | 260 | let directive = parseDirective s
|
258 | 261 | if directive == Right CppDumpState
|
259 | 262 | then return (Just "\ndumped state\n")
|
260 | 263 | else do
|
261 | 264 | case directive of
|
262 | - Left err -> error $ show (err, s)
|
|
265 | + Left err -> Lexer.addError $ mkPlainErrorMsgEnvelope loc $ PsErrGhcCpp (text err)
|
|
263 | 266 | Right (CppInclude filename) -> do
|
264 | 267 | ppInclude filename
|
265 | 268 | Right (CppDefine name args def) -> do
|
... | ... | @@ -280,14 +283,14 @@ processCpp ss = do |
280 | 283 | acceptStateChange ar
|
281 | 284 | Right CppElse -> do
|
282 | 285 | accepting <- getAccepting
|
283 | - ar <- setAccepting (not accepting)
|
|
286 | + ar <- setAccepting loc (text "#else") (not accepting)
|
|
284 | 287 | acceptStateChange ar
|
285 | 288 | Right (CppElIf cond) -> do
|
286 | 289 | val <- cppCond cond
|
287 | - ar <- setAccepting val
|
|
290 | + ar <- setAccepting loc (text "#elif") val
|
|
288 | 291 | acceptStateChange ar
|
289 | 292 | Right CppEndif -> do
|
290 | - ar <- popAccepting
|
|
293 | + ar <- popAccepting loc
|
|
291 | 294 | acceptStateChange ar
|
292 | 295 | Right CppDumpState -> do
|
293 | 296 | return ()
|
... | ... | @@ -298,15 +301,8 @@ processCpp ss = do |
298 | 301 | acceptStateChange :: AcceptingResult -> PP ()
|
299 | 302 | acceptStateChange ArNoChange = return ()
|
300 | 303 | acceptStateChange ArNowIgnoring = do
|
301 | - -- alr <- Lexer.getAlrState
|
|
302 | - -- s <- getPpState
|
|
303 | - -- let s = trace ("acceptStateChange:ArNowIgnoring") s'
|
|
304 | - -- setPpState (s { pp_alr_state = Just alr})
|
|
305 | 304 | Lexer.startSkipping
|
306 | 305 | acceptStateChange ArNowAccepting = do
|
307 | - -- s <- getPpState
|
|
308 | - -- let s = trace ("acceptStateChange:ArNowAccepting") s'
|
|
309 | - -- mapM_ Lexer.setAlrState (pp_alr_state s)
|
|
310 | 306 | _ <- Lexer.stopSkipping
|
311 | 307 | return ()
|
312 | 308 |
... | ... | @@ -32,6 +32,7 @@ module GHC.Parser.PreProcess.State ( |
32 | 32 | ghcCppEnabled,
|
33 | 33 | setInLinePragma,
|
34 | 34 | getInLinePragma,
|
35 | + addGhcCPPError,
|
|
35 | 36 | ) where
|
36 | 37 | |
37 | 38 | import Data.List.NonEmpty ((<|))
|
... | ... | @@ -41,12 +42,15 @@ import Data.Map.Strict qualified as Map |
41 | 42 | import Data.Maybe (isJust)
|
42 | 43 | import GHC.Base
|
43 | 44 | import GHC.Data.StringBuffer
|
45 | +import GHC.Parser.Errors.Types (PsMessage (PsErrGhcCpp))
|
|
44 | 46 | import GHC.Parser.Lexer (P (..), PState (..), ParseResult (..))
|
45 | 47 | import GHC.Parser.Lexer qualified as Lexer
|
46 | 48 | import GHC.Parser.PreProcess.ParserM (Token (..))
|
47 | 49 | import GHC.Types.SrcLoc
|
50 | +import GHC.Utils.Error
|
|
48 | 51 | |
49 | 52 | import GHC.Prelude
|
53 | +import GHC.Utils.Outputable (text, (<+>))
|
|
50 | 54 | |
51 | 55 | -- ---------------------------------------------------------------------
|
52 | 56 | |
... | ... | @@ -191,20 +195,22 @@ pushAccepting on = do |
191 | 195 | |
192 | 196 | -- Note: this is only ever called in the context of a pp group (i.e.
|
193 | 197 | -- after pushAccepting) from processing #else or #elif
|
194 | -setAccepting :: Bool -> PP AcceptingResult
|
|
195 | -setAccepting on = do
|
|
198 | +setAccepting :: SrcSpan -> SDoc -> Bool -> PP AcceptingResult
|
|
199 | +setAccepting loc ctx on = do
|
|
196 | 200 | current <- getAccepting
|
197 | 201 | parent_scope <- parentScope
|
198 | 202 | let parent_on = pp_accepting parent_scope
|
199 | 203 | current_scope <- getScope
|
200 | 204 | let group_state = pp_group_state current_scope
|
201 | 205 | let possible_accepting = parent_on && on
|
202 | - let (new_group_state, accepting) =
|
|
203 | - case (group_state, possible_accepting) of
|
|
204 | - (PpNoGroup, _) -> error "setAccepting for state PpNoGroup" -- AZ: Tested in GhcCpp02
|
|
205 | - (PpInGroupStillInactive, True) -> (PpInGroupHasBeenActive, True)
|
|
206 | - (PpInGroupStillInactive, False) -> (PpInGroupStillInactive, False)
|
|
207 | - (PpInGroupHasBeenActive, _) -> (PpInGroupHasBeenActive, False)
|
|
206 | + (new_group_state, accepting) <-
|
|
207 | + case (group_state, possible_accepting) of
|
|
208 | + (PpNoGroup, _) -> do
|
|
209 | + addGhcCPPError loc (ctx <+> text "without #if")
|
|
210 | + return (PpNoGroup, True)
|
|
211 | + (PpInGroupStillInactive, True) -> return (PpInGroupHasBeenActive, True)
|
|
212 | + (PpInGroupStillInactive, False) -> return (PpInGroupStillInactive, False)
|
|
213 | + (PpInGroupHasBeenActive, _) -> return (PpInGroupHasBeenActive, False)
|
|
208 | 214 | |
209 | 215 | -- let (new_group_state, accepting)
|
210 | 216 | -- = trace ("setAccepting:" ++ show ((group_state, possible_accepting), (new_group_state', accepting'))) (new_group_state', accepting')
|
... | ... | @@ -231,19 +237,29 @@ acceptingStateChange old new = |
231 | 237 | _ -> ArNoChange
|
232 | 238 | |
233 | 239 | -- Exit a scope group
|
234 | -popAccepting :: PP AcceptingResult
|
|
235 | -popAccepting =
|
|
236 | - P $ \s ->
|
|
237 | - let
|
|
238 | - current = scopeValue $ pp_scope (pp s)
|
|
239 | - new_scope = case pp_scope (pp s) of
|
|
240 | - c :| [] -> c :| []
|
|
241 | - -- c :| [] -> (trace ("popAccepting:keeping old:" ++ show c) c) :| []
|
|
242 | - _ :| (h : t) -> h :| t
|
|
243 | - in
|
|
244 | - POk
|
|
245 | - s{pp = (pp s){pp_scope = new_scope}}
|
|
246 | - (acceptingStateChange current (scopeValue new_scope))
|
|
240 | +popAccepting :: SrcSpan -> PP AcceptingResult
|
|
241 | +-- popAccepting =
|
|
242 | +-- P $ \s ->
|
|
243 | +-- let
|
|
244 | +-- current = scopeValue $ pp_scope (pp s)
|
|
245 | +-- new_scope = case pp_scope (pp s) of
|
|
246 | +-- c :| [] -> c :| []
|
|
247 | +-- -- c :| [] -> (trace ("popAccepting:keeping old:" ++ show c) c) :| []
|
|
248 | +-- _ :| (h : t) -> h :| t
|
|
249 | +-- in
|
|
250 | +-- POk
|
|
251 | +-- s{pp = (pp s){pp_scope = new_scope}}
|
|
252 | +-- (acceptingStateChange current (scopeValue new_scope))
|
|
253 | +popAccepting loc = do
|
|
254 | + scopes <- getScopes
|
|
255 | + new_scope <- case scopes of
|
|
256 | + c :| [] -> do
|
|
257 | + addGhcCPPError loc (text "#endif without #if")
|
|
258 | + return (c :| [])
|
|
259 | + _ :| (h : t) -> return (h :| t)
|
|
260 | + setScopes new_scope
|
|
261 | + let current = scopeValue scopes
|
|
262 | + return (acceptingStateChange current (scopeValue new_scope))
|
|
247 | 263 | |
248 | 264 | scopeValue :: NonEmpty PpScope -> Bool
|
249 | 265 | scopeValue s = pp_accepting $ NonEmpty.head s
|
... | ... | @@ -280,6 +296,13 @@ setScope scope = |
280 | 296 | in
|
281 | 297 | POk s{pp = (pp s){pp_scope = new_scope}} ()
|
282 | 298 | |
299 | +getScopes :: PP (NonEmpty PpScope)
|
|
300 | +getScopes = P $ \s -> POk s (pp_scope (pp s))
|
|
301 | + |
|
302 | +setScopes :: (NonEmpty PpScope) -> PP ()
|
|
303 | +setScopes new_scope =
|
|
304 | + P $ \s -> POk s{pp = (pp s){pp_scope = new_scope}} ()
|
|
305 | + |
|
283 | 306 | {-
|
284 | 307 | Note [PpScope stack]
|
285 | 308 | ~~~~~~~~~~~~~~~~~~~~
|
... | ... | @@ -404,3 +427,7 @@ insertMacroDef (MacroName name args) def md = |
404 | 427 | Just dm -> Map.insert name (Map.insert arity (args, def) dm) md
|
405 | 428 | |
406 | 429 | -- ---------------------------------------------------------------------
|
430 | + |
|
431 | +addGhcCPPError :: SrcSpan -> SDoc -> P p ()
|
|
432 | +addGhcCPPError loc err =
|
|
433 | + Lexer.addError $ mkPlainErrorMsgEnvelope loc $ PsErrGhcCpp err |
... | ... | @@ -371,6 +371,7 @@ type family GhcDiagnosticCode c = n | n -> c where |
371 | 371 | GhcDiagnosticCode "PsErrSpecExprMultipleTypeAscription" = 62037
|
372 | 372 | GhcDiagnosticCode "PsWarnSpecMultipleTypeAscription" = 73026
|
373 | 373 | GhcDiagnosticCode "PsWarnPatternNamespaceSpecifier" = 68383
|
374 | + GhcDiagnosticCode "PsErrGhcCpp" = 93098
|
|
374 | 375 | |
375 | 376 | -- Driver diagnostic codes
|
376 | 377 | GhcDiagnosticCode "DriverMissingHomeModules" = 32850
|
1 | +GhcCpp02.hs:5:1: error: [GHC-93098] #else without #if
|
|
2 | + |
|
3 | +GhcCpp02.hs:7:1: error: [GHC-93098] #endif without #if
|
|
4 | + |
... | ... | @@ -20,4 +20,4 @@ test('GhcCpp01', |
20 | 20 | compile,
|
21 | 21 | ['-ddump-ghc-cpp -dkeep-comments'])
|
22 | 22 | |
23 | -test('GhcCpp02', normal, compile, ['']) |
|
\ No newline at end of file | ||
23 | +test('GhcCpp02', normal, compile_fail, ['']) |
|
\ No newline at end of file |
1 | 1 | module PreProcess where
|
2 | 2 | |
3 | 3 | import Data.List
|
4 | +import Data.Maybe (fromMaybe, listToMaybe)
|
|
4 | 5 | import qualified Data.Map as Map
|
5 | 6 | import Debug.Trace
|
6 | 7 | import GHC hiding (addSourceToTokens)
|
... | ... | @@ -20,6 +21,7 @@ import GHC.Types.SrcLoc |
20 | 21 | import GHC.Utils.Error
|
21 | 22 | import GHC.Utils.Outputable
|
22 | 23 | import GHC.Utils.Panic.Plain
|
24 | +import GHC.Parser.Errors.Types (PsMessage(PsErrGhcCpp))
|
|
23 | 25 | |
24 | 26 | import Macro
|
25 | 27 | import ParsePP
|
... | ... | @@ -241,7 +243,7 @@ ppLexer queueComments cont = |
241 | 243 | pushContinuation tk
|
242 | 244 | contIgnoreTok tk
|
243 | 245 | else do
|
244 | - mdump <- processCppToks s
|
|
246 | + mdump <- processCppToks tk
|
|
245 | 247 | case mdump of
|
246 | 248 | Just dump ->
|
247 | 249 | -- We have a dump of the state, put it into an ignored token
|
... | ... | @@ -270,25 +272,25 @@ ppLexer queueComments cont = |
270 | 272 | |
271 | 273 | -- ---------------------------------------------------------------------
|
272 | 274 | |
273 | -processCppToks :: FastString -> PP (Maybe String)
|
|
275 | +processCppToks :: Located Lexer.Token -> PP (Maybe String)
|
|
274 | 276 | processCppToks fs = do
|
275 | 277 | let
|
276 | 278 | get (L _ (ITcpp False s _)) = unpackFS s
|
277 | 279 | get (L _ (ITcpp True s _)) = init $ unpackFS s
|
278 | - get _ = error "should not"
|
|
280 | + get _ = panic "Should be ITcpp"
|
|
279 | 281 | -- Combine any prior continuation tokens
|
280 | 282 | cs <- popContinuation
|
281 | - processCpp (reverse $ unpackFS fs : map get cs)
|
|
283 | + let loc = combineLocs fs (fromMaybe fs (listToMaybe cs))
|
|
284 | + processCpp loc (concat $ reverse $ map get (fs:cs))
|
|
282 | 285 | |
283 | -processCpp :: [String] -> PP (Maybe String)
|
|
284 | -processCpp ss = do
|
|
285 | - let s = concat ss
|
|
286 | +processCpp :: SrcSpan -> String -> PP (Maybe String)
|
|
287 | +processCpp loc s = do
|
|
286 | 288 | let directive = parseDirective s
|
287 | 289 | if directive == Right CppDumpState
|
288 | 290 | then return (Just "\ndumped state\n")
|
289 | 291 | else do
|
290 | 292 | case directive of
|
291 | - Left err -> error $ show (err, s)
|
|
293 | + Left err -> Lexer.addError $ mkPlainErrorMsgEnvelope loc $ PsErrGhcCpp (fsLit (show err))
|
|
292 | 294 | Right (CppInclude filename) -> do
|
293 | 295 | ppInclude filename
|
294 | 296 | Right (CppDefine name args def) -> do
|
... | ... | @@ -309,11 +311,11 @@ processCpp ss = do |
309 | 311 | acceptStateChange ar
|
310 | 312 | Right CppElse -> do
|
311 | 313 | accepting <- getAccepting
|
312 | - ar <- setAccepting (not accepting)
|
|
314 | + ar <- setAccepting loc (not accepting)
|
|
313 | 315 | acceptStateChange ar
|
314 | 316 | Right (CppElIf cond) -> do
|
315 | 317 | val <- cppCond cond
|
316 | - ar <- setAccepting val
|
|
318 | + ar <- setAccepting loc val
|
|
317 | 319 | acceptStateChange ar
|
318 | 320 | Right CppEndif -> do
|
319 | 321 | ar <- popAccepting
|
... | ... | @@ -32,17 +32,22 @@ module State ( |
32 | 32 | ghcCppEnabled,
|
33 | 33 | setInLinePragma,
|
34 | 34 | getInLinePragma,
|
35 | + addGhcCPPError,
|
|
35 | 36 | ) where
|
36 | 37 | |
37 | 38 | import Data.List.NonEmpty ((<|))
|
38 | -import qualified Data.List.NonEmpty as NonEmpty
|
|
39 | -import Data.Map (Map)
|
|
40 | -import qualified Data.Map as Map
|
|
39 | +import Data.List.NonEmpty qualified as NonEmpty
|
|
40 | +import Data.Map.Strict (Map)
|
|
41 | +import Data.Map.Strict qualified as Map
|
|
41 | 42 | import Data.Maybe (isJust)
|
42 | 43 | import GHC.Base
|
44 | +import GHC.Data.FastString
|
|
43 | 45 | import GHC.Data.StringBuffer
|
44 | 46 | import GHC.Parser.Lexer (P (..), PState (..), ParseResult (..))
|
45 | -import qualified GHC.Parser.Lexer as Lexer
|
|
47 | +import GHC.Parser.Lexer qualified as Lexer
|
|
48 | +import GHC.Parser.Errors.Types (PsMessage(PsErrGhcCpp))
|
|
49 | +import GHC.Utils.Error
|
|
50 | +-- import GHC.Parser.PreProcess.ParserM (Token (..))
|
|
46 | 51 | import GHC.Types.SrcLoc
|
47 | 52 | import ParserM (Token (..))
|
48 | 53 | |
... | ... | @@ -192,20 +197,22 @@ pushAccepting on = do |
192 | 197 | |
193 | 198 | -- Note: this is only ever called in the context of a pp group (i.e.
|
194 | 199 | -- after pushAccepting) from processing #else or #elif
|
195 | -setAccepting :: Bool -> PP AcceptingResult
|
|
196 | -setAccepting on = do
|
|
200 | +setAccepting :: SrcSpan -> Bool -> PP AcceptingResult
|
|
201 | +setAccepting loc on = do
|
|
197 | 202 | current <- getAccepting
|
198 | 203 | parent_scope <- parentScope
|
199 | 204 | let parent_on = pp_accepting parent_scope
|
200 | 205 | current_scope <- getScope
|
201 | 206 | let group_state = pp_group_state current_scope
|
202 | 207 | let possible_accepting = parent_on && on
|
203 | - let (new_group_state, accepting) =
|
|
208 | + (new_group_state, accepting) <-
|
|
204 | 209 | case (group_state, possible_accepting) of
|
205 | - (PpNoGroup, _) -> error "setAccepting for state PpNoGroup"
|
|
206 | - (PpInGroupStillInactive, True) -> (PpInGroupHasBeenActive, True)
|
|
207 | - (PpInGroupStillInactive, False) -> (PpInGroupStillInactive, False)
|
|
208 | - (PpInGroupHasBeenActive, _) -> (PpInGroupHasBeenActive, False)
|
|
210 | + (PpNoGroup, _) -> do
|
|
211 | + addGhcCPPError loc "setAccepting for state PpNoGroup"
|
|
212 | + return (PpNoGroup, True)
|
|
213 | + (PpInGroupStillInactive, True) -> return (PpInGroupHasBeenActive, True)
|
|
214 | + (PpInGroupStillInactive, False) -> return (PpInGroupStillInactive, False)
|
|
215 | + (PpInGroupHasBeenActive, _) -> return (PpInGroupHasBeenActive, False)
|
|
209 | 216 | |
210 | 217 | -- let (new_group_state, accepting)
|
211 | 218 | -- = trace ("setAccepting:" ++ show ((group_state, possible_accepting), (new_group_state', accepting'))) (new_group_state', accepting')
|
... | ... | @@ -405,3 +412,7 @@ insertMacroDef (MacroName name args) def md = |
405 | 412 | Just dm -> Map.insert name (Map.insert arity (args, def) dm) md
|
406 | 413 | |
407 | 414 | -- ---------------------------------------------------------------------
|
415 | + |
|
416 | +addGhcCPPError :: SrcSpan -> String -> P p ()
|
|
417 | +addGhcCPPError loc err
|
|
418 | + = Lexer.addError $ mkPlainErrorMsgEnvelope loc $ PsErrGhcCpp (fsLit err) |