summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Gröber <dxld@darkboxed.org>2019-05-25 13:57:45 +0200
committerMarge Bot <ben+marge-bot@smart-cactus.org>2019-05-30 16:44:08 -0400
commit99e7276982fe41dca0098e37a9cbf71091c3e275 (patch)
tree92f37e76956e161696926ea65c32505f2f56244d
parent18d3f01d9abe2994b2b3d07b67ee9616c3553e16 (diff)
downloadhaskell-99e7276982fe41dca0098e37a9cbf71091c3e275.tar.gz
Catch preprocessor errors in downsweep
This changes the way preprocessor failures are presented to the user. Previously the user would simply get an unlocated message on stderr such as: `gcc' failed in phase `C pre-processor'. (Exit code: 1) Now at the problematic source file is mentioned: A.hs:1:1: error: `gcc' failed in phase `C pre-processor'. (Exit code: 1) This also makes live easier for GHC API clients as the preprocessor error is now thrown as a SourceError exception.
-rw-r--r--compiler/main/DriverPipeline.hs12
-rw-r--r--compiler/main/GhcMake.hs17
-rw-r--r--testsuite/tests/driver/T8602/T8602.stderr4
-rw-r--r--testsuite/tests/ghc-api/downsweep/PartialDownsweep.darwin.stderr16
-rw-r--r--testsuite/tests/ghc-api/downsweep/PartialDownsweep.hs57
-rw-r--r--testsuite/tests/ghc-api/downsweep/PartialDownsweep.stderr14
-rw-r--r--testsuite/tests/ghc-api/downsweep/all.T3
7 files changed, 95 insertions, 28 deletions
diff --git a/compiler/main/DriverPipeline.hs b/compiler/main/DriverPipeline.hs
index 9ac973cbc4..78e4a810d7 100644
--- a/compiler/main/DriverPipeline.hs
+++ b/compiler/main/DriverPipeline.hs
@@ -64,6 +64,8 @@ import Hooks
import qualified GHC.LanguageExtensions as LangExt
import FileCleanup
import Ar
+import Bag ( unitBag )
+import FastString ( mkFastString )
import Exception
import System.Directory
@@ -91,8 +93,11 @@ preprocess :: HscEnv
-> Maybe StringBuffer
-- ^ optional buffer to use instead of reading input file
-> Maybe Phase -- ^ starting phase
- -> IO (DynFlags, FilePath)
+ -> IO (Either ErrorMessages (DynFlags, FilePath))
preprocess hsc_env input_fn mb_input_buf mb_phase =
+ handleSourceError (\err -> return (Left (srcErrorMessages err))) $
+ ghandle handler $
+ fmap Right $
ASSERT2(isJust mb_phase || isHaskellSrcFilename input_fn, text input_fn)
runPipeline anyHsc hsc_env (input_fn, mb_input_buf, fmap RealPhase mb_phase)
Nothing
@@ -101,6 +106,11 @@ preprocess hsc_env input_fn mb_input_buf mb_phase =
(Temporary TFL_GhcSession)
Nothing{-no ModLocation-}
[]{-no foreign objects-}
+ where
+ srcspan = srcLocSpan $ mkSrcLoc (mkFastString input_fn) 1 1
+ handler (ProgramError msg) = return $ Left $ unitBag $
+ mkPlainErrMsg (hsc_dflags hsc_env) srcspan $ text msg
+ handler ex = throwGhcExceptionIO ex
-- ---------------------------------------------------------------------------
diff --git a/compiler/main/GhcMake.hs b/compiler/main/GhcMake.hs
index 341356f775..f3a1cfaaca 100644
--- a/compiler/main/GhcMake.hs
+++ b/compiler/main/GhcMake.hs
@@ -2489,19 +2489,6 @@ getObjTimestamp location is_boot
= if is_boot == IsBoot then return Nothing
else modificationTimeIfExists (ml_obj_file location)
-
-preprocessFile :: HscEnv
- -> FilePath
- -> Maybe Phase -- ^ Starting phase
- -> Maybe (StringBuffer,UTCTime)
- -> IO (DynFlags, FilePath, StringBuffer)
-preprocessFile hsc_env src_fn mb_phase maybe_buf
- = do
- (dflags', hspp_fn)
- <- preprocess hsc_env src_fn (fst <$> maybe_buf) mb_phase
- buf <- hGetStringBuffer hspp_fn
- return (dflags', hspp_fn, buf)
-
data PreprocessedImports
= PreprocessedImports
{ pi_local_dflags :: DynFlags
@@ -2523,8 +2510,8 @@ getPreprocessedImports
-> ExceptT ErrorMessages IO PreprocessedImports
getPreprocessedImports hsc_env src_fn mb_phase maybe_buf = do
(pi_local_dflags, pi_hspp_fn)
- <- liftIO $ preprocess hsc_env src_fn (fst <$> maybe_buf) mb_phase
- pi_hscpp_buf <- liftIO $ hGetStringBuffer pi_hspp_fn
+ <- ExceptT $ preprocess hsc_env src_fn (fst <$> maybe_buf) mb_phase
+ pi_hspp_buf <- liftIO $ hGetStringBuffer pi_hspp_fn
(pi_srcimps, pi_theimps, L pi_mod_name_loc pi_mod_name)
<- ExceptT $ getImports pi_local_dflags pi_hspp_buf pi_hspp_fn src_fn
return PreprocessedImports {..}
diff --git a/testsuite/tests/driver/T8602/T8602.stderr b/testsuite/tests/driver/T8602/T8602.stderr
index eb28842f54..4b0c4a5373 100644
--- a/testsuite/tests/driver/T8602/T8602.stderr
+++ b/testsuite/tests/driver/T8602/T8602.stderr
@@ -1,2 +1,4 @@
A B C
-`t8602.sh' failed in phase `Haskell pre-processor'. (Exit code: 1)
+
+A.hs:1:1: error:
+ `t8602.sh' failed in phase `Haskell pre-processor'. (Exit code: 1)
diff --git a/testsuite/tests/ghc-api/downsweep/PartialDownsweep.darwin.stderr b/testsuite/tests/ghc-api/downsweep/PartialDownsweep.darwin.stderr
new file mode 100644
index 0000000000..c9cd0f216d
--- /dev/null
+++ b/testsuite/tests/ghc-api/downsweep/PartialDownsweep.darwin.stderr
@@ -0,0 +1,16 @@
+== Parse error in export list
+== Parse error in export list with bypass module
+== Parse error in import list
+== CPP preprocessor error
+
+B.hs:2:2: #elif without #if
+ #elif <- cpp error here
+ ^
+1 error generated.
+== CPP preprocessor error with bypass
+
+B.hs:2:2: #elif without #if
+ #elif <- cpp error here
+ ^
+1 error generated.
+== Import error
diff --git a/testsuite/tests/ghc-api/downsweep/PartialDownsweep.hs b/testsuite/tests/ghc-api/downsweep/PartialDownsweep.hs
index f3c379a3fb..fb91fb6c1f 100644
--- a/testsuite/tests/ghc-api/downsweep/PartialDownsweep.hs
+++ b/testsuite/tests/ghc-api/downsweep/PartialDownsweep.hs
@@ -45,7 +45,8 @@ main = do
runGhc (Just libdir) $ do
dflags0 <- getSessionDynFlags
(dflags1, _, _) <- parseDynamicFlags dflags0 $ map noLoc $
- [ -- "-v3"
+ [ "-fno-diagnostics-show-caret"
+ -- , "-v3"
] ++ args
_ <- setSessionDynFlags dflags1
@@ -65,6 +66,23 @@ main = do
sort (map (moduleNameString . moduleName . ms_mod) mss) == ["A"]
)
+ go "Parse error in export list with bypass module"
+ [ [ "module A where"
+ , "import B"
+ , "import C"
+ ]
+ , [ "module B !parse_error where"
+ , "import D"
+ ]
+ , [ "module C where"
+ , "import D"
+ ]
+ , [ "module D where"
+ ]
+ ]
+ (\mss -> return $
+ sort (map (moduleNameString . moduleName . ms_mod) mss) == ["A", "C", "D"]
+ )
go "Parse error in import list"
[ [ "module A where"
, "import B"
@@ -83,24 +101,40 @@ main = do
sort (map (moduleNameString . moduleName . ms_mod) mss) == ["A", "B"]
)
- go "Parse error in export list with bypass module"
+ go "CPP preprocessor error"
[ [ "module A where"
, "import B"
- , "import C"
]
- , [ "module B !parse_error where"
- , "import D"
+ , [ "{-# LANGUAGE CPP #-}"
+ , "#elif <- cpp error here"
+ , "module B where"
+ , "import C"
]
, [ "module C where"
- , "import D"
]
- , [ "module D where"
+ ]
+ (\mss -> return $
+ sort (map (moduleNameString . moduleName . ms_mod) mss) == ["A"]
+ )
+
+ go "CPP preprocessor error with bypass"
+ [ [ "module A where"
+ , "import B"
+ , "import C"
+ ]
+ , [ "{-# LANGUAGE CPP #-}"
+ , "#elif <- cpp error here"
+ , "module B where"
+ , "import C"
+ ]
+ , [ "module C where"
]
]
(\mss -> return $
- sort (map (moduleNameString . moduleName . ms_mod) mss) == ["A", "C", "D"]
+ sort (map (moduleNameString . moduleName . ms_mod) mss) == ["A", "C"]
)
+
errored <- readIORef any_failed
when errored $ exitFailure
return ()
@@ -125,5 +159,8 @@ go label mods cnd =
writeMod :: [String] -> IO ()
-writeMod src@(head -> stripPrefix "module " -> Just (takeWhile (/=' ') -> mod))
- = writeFile (mod++".hs") $ unlines src
+writeMod src =
+ writeFile (mod++".hs") $ unlines src
+ where
+ Just modline = find ("module" `isPrefixOf`) src
+ Just (takeWhile (/=' ') -> mod) = stripPrefix "module " modline
diff --git a/testsuite/tests/ghc-api/downsweep/PartialDownsweep.stderr b/testsuite/tests/ghc-api/downsweep/PartialDownsweep.stderr
index 11fd4b73c8..9e5f6d83dc 100644
--- a/testsuite/tests/ghc-api/downsweep/PartialDownsweep.stderr
+++ b/testsuite/tests/ghc-api/downsweep/PartialDownsweep.stderr
@@ -1,3 +1,15 @@
== Parse error in export list
-== Parse error in import list
== Parse error in export list with bypass module
+== Parse error in import list
+== CPP preprocessor error
+
+B.hs:2:0: error:
+ error: #elif without #if
+ #elif <- cpp error here
+
+== CPP preprocessor error with bypass
+
+B.hs:2:0: error:
+ error: #elif without #if
+ #elif <- cpp error here
+
diff --git a/testsuite/tests/ghc-api/downsweep/all.T b/testsuite/tests/ghc-api/downsweep/all.T
index d7ed778f8e..18ed26ac88 100644
--- a/testsuite/tests/ghc-api/downsweep/all.T
+++ b/testsuite/tests/ghc-api/downsweep/all.T
@@ -1,5 +1,8 @@
test('PartialDownsweep',
[ extra_run_opts('"' + config.libdir + '"')
+ , when(opsys('darwin'),
+ use_specs({'stderr' : 'PartialDownsweep.darwin.stderr'})
+ )
],
compile_and_run,
['-package ghc'])