Pass preprocessor options to C compiler when building foreign C files (#16737)
authorZejun Wu <watashi@fb.com>
Tue, 4 Jun 2019 22:25:10 +0000 (15:25 -0700)
committerBen Gamari <ben@smart-cactus.org>
Sun, 23 Jun 2019 17:27:12 +0000 (13:27 -0400)
(cherry picked from commit cfd3e0f1cfd16c8f35cae139d2a871a32eb4d2e1)

compiler/main/DriverPipeline.hs
testsuite/tests/driver/T16737.hs [new file with mode: 0644]
testsuite/tests/driver/T16737.stdout [new file with mode: 0644]
testsuite/tests/driver/T16737include/T16737.h [new file with mode: 0644]
testsuite/tests/driver/all.T

index 5d3dbaf..39d8188 100644 (file)
@@ -1193,9 +1193,6 @@ runPhase (RealPhase Cmm) input_fn dflags
 -----------------------------------------------------------------------------
 -- Cc phase
 
--- we don't support preprocessing .c files (with -E) now.  Doing so introduces
--- way too many hacks, and I can't say I've ever used it anyway.
-
 runPhase (RealPhase cc_phase) input_fn dflags
    | any (cc_phase `eqPhase`) [Cc, Ccxx, HCc, Cobjc, Cobjcxx]
    = do
@@ -1217,6 +1214,16 @@ runPhase (RealPhase cc_phase) input_fn dflags
               (includePathsQuote cmdline_include_paths)
         let include_paths = include_paths_quote ++ include_paths_global
 
+        -- pass -D or -optP to preprocessor when compiling foreign C files
+        -- (#16737). Doing it in this way is simpler and also enable the C
+        -- compiler to performs preprocessing and parsing in a single pass,
+        -- but it may introduce inconsistency if a different pgm_P is specified.
+        let more_preprocessor_opts = concat
+              [ ["-Xpreprocessor", i]
+              | not hcc
+              , i <- getOpts dflags opt_P
+              ]
+
         let gcc_extra_viac_flags = extraGccViaCFlags dflags
         let pic_c_flags = picCCOpts dflags
 
@@ -1226,7 +1233,7 @@ runPhase (RealPhase cc_phase) input_fn dflags
         -- hc code doesn't not #include any header files anyway, so these
         -- options aren't necessary.
         pkg_extra_cc_opts <- liftIO $
-          if cc_phase `eqPhase` HCc
+          if hcc
              then return []
              else getPackageExtraCcOpts dflags pkgs
 
@@ -1317,6 +1324,7 @@ runPhase (RealPhase cc_phase) input_fn dflags
                        ++ [ "-include", ghcVersionH ]
                        ++ framework_paths
                        ++ include_paths
+                       ++ more_preprocessor_opts
                        ++ pkg_extra_cc_opts
                        ))
 
diff --git a/testsuite/tests/driver/T16737.hs b/testsuite/tests/driver/T16737.hs
new file mode 100644 (file)
index 0000000..daf8306
--- /dev/null
@@ -0,0 +1,32 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# OPTIONS_GHC -DFOO=2 -optP=-DBAR=3 -optc=-DBAZ=5 -optcxx=-DBAZ=7 #-}
+
+import Language.Haskell.TH.Syntax
+
+do
+  let code = unlines
+        [ "#if defined(__cplusplus)"
+        , "extern \"C\" {"
+        , "#endif"
+        , "#include <T16737.h>"
+        , "int FUN(void) {"
+        , "  return FOO * BAR * BAZ;"
+        , "}"
+        , "#if defined(__cplusplus)"
+        , "}"
+        , "#endif"
+        ]
+  addForeignSource LangC code
+  addForeignSource LangCxx code
+  pure []
+
+foreign import ccall unsafe "c_value"
+  c_value :: IO Int
+
+foreign import ccall unsafe "cxx_value"
+  cxx_value :: IO Int
+
+main :: IO ()
+main = do
+  print =<< c_value
+  print =<< cxx_value
diff --git a/testsuite/tests/driver/T16737.stdout b/testsuite/tests/driver/T16737.stdout
new file mode 100644 (file)
index 0000000..8a3609b
--- /dev/null
@@ -0,0 +1,2 @@
+30
+42
diff --git a/testsuite/tests/driver/T16737include/T16737.h b/testsuite/tests/driver/T16737include/T16737.h
new file mode 100644 (file)
index 0000000..08c7ca8
--- /dev/null
@@ -0,0 +1,7 @@
+#pragma once
+
+#if defined(__cplusplus)
+#define FUN cxx_value
+#else
+#define FUN c_value
+#endif
index 02eeeb3..397fdc5 100644 (file)
@@ -287,3 +287,4 @@ test('inline-check', omit_ways(['hpc', 'profasm'])
 
 test('T14452', [], run_command, ['$MAKE -s --no-print-directory T14452'])
 test('T15396', normal, compile_and_run, ['-package ghc'])
+test('T16737', [extra_files(['T16737include/'])], compile_and_run, ['-optP=-isystem -optP=T16737include'])