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) |