Skip to content

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.

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.

To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information