ghc 8.8 hangs on empty preprocessor response file
Summary
GHC hangs indefinitely when compiling a simple library with coverage enabled when the preprocessor flags include an empty response file.
- This was originally reported here: https://github.com/tweag/rules_haskell/issues/1324
- The following similar issue seems to have the same root cause: https://github.com/tweag/rules_haskell/issues/1323
- This seems to be a regression introduced by the forwarding of preprocessor flags to gcc, see #17185 (closed).
Steps to reproduce
Execute the following commands and observe the compilation hang indefinitely.
touch cpp-args
cat >Lib.hs <<EOF
module Lib where
EOF
ghc -optP@cpp-args -optP-DX -fhpc Lib.hs
Expected behavior
Compilation should terminate successfully.
Environment
- GHC version used: 8.8.2
I have also reproduced this with 8.8.3 and 8.10.1. In contrast compilation succeeds as expected with GHC 8.6.5. The versions 8.6.5 and 8.8.2 were installed from the following PPA http://ppa.launchpad.net/hvr/ghc/ubuntu. The versions 8.8.3 and 8.10.1 were installed using Nix.
Optional:
- Operating System: Ubuntu 19.10
- System Architecture: x86_64
Further Information
- The issue can be avoided if
cpp-args
contains at least one argument, e.g.-Waddress-of-packed-member
. - The issue can also be avoided by removing the
-optP@cpp-args
flag. - If instead
-optP-DX
is removed then compilation fails with following error:gcc: error: missing argument to ‘-Xpreprocessor’ `gcc' failed in phase `C Compiler'. (Exit code: 1)
Running strace -f -s 10000 ghc -optP@cpp-args -optP-DX -fhpc Lib.hs
shows that cc1
fails with the following error:
21895 write(2, "cc1: error: command line option \342\200\230-Xpreprocessor /tmp/ghc21889_0/ghc_3.c\342\200\231 is valid for the driver but not for C\n", 115) = 115
And ghc
then hangs on the following sequence of reads
...
21890 read(4, "\1\0\0\0\0\0\0\0", 8) = 8
21890 read(4, "\1\0\0\0\0\0\0\0", 8) = 8
21890 read(4, "\1\0\0\0\0\0\0\0", 8) = 8
21890 read(4, "\1\0\0\0\0\0\0\0", 8) = 8
GHC writes the following response file for gcc
"-DTABLES_NEXT_TO_CODE"
"-x"
"c"
"/tmp/ghc11759_0/ghc_3.c"
"-o"
"/tmp/ghc11759_0/ghc_4.s"
"-no-pie"
"-fno-PIC"
"-Wimplicit"
"-S"
"-include"
"/opt/ghc/8.8.2/lib/ghc-8.8.2/include/ghcversion.h"
"-iquote."
"-I/opt/ghc/8.8.2/lib/ghc-8.8.2/base-4.13.0.0/include"
"-I/opt/ghc/8.8.2/lib/ghc-8.8.2/integer-gmp-1.0.2.0/include"
"-I/opt/ghc/8.8.2/lib/ghc-8.8.2/include"
"-Xpreprocessor"
"@cpp-args"
"-Xpreprocessor"
"-DX"
Note the -Xpreprocessor @cpp-args -Xpreprocessor -DX
flags.
I haven't looked at the relevant gcc sources, but by looking at the trace my guess would be that gcc interprets @cpp-args
as its own response file instead of forwarding it to cc1
. At least gcc reads cpp-args
and calls cc1
with the flags ... -D X ... -Xpreprocessor /tmp/ghc11759_0/ghc_3.c ...
. I'm speculating, but this could be explained by the following expansion of gcc's commandline -Xpreprocessor -Xpreprocessor -DX
due to inlining the contents of cpp-args
. It would also explain why ghc -optP@cpp-args -fhpc Lib.hs
fails with
gcc: error: missing argument to ‘-Xpreprocessor’
via the expansion -Xpreprocessor @cpp-args
by GHC and then -Xpreprocessor
by inlining cpp-args
within gcc
.