[Driver][gcov] Derive .gcno .gcda file names from -o and -dumpdir
authorFangrui Song <i@maskray.me>
Wed, 17 May 2023 07:43:00 +0000 (00:43 -0700)
committerFangrui Song <i@maskray.me>
Wed, 17 May 2023 07:43:00 +0000 (00:43 -0700)
commitd515b8125364ef85fb100f1430b2174ed816cc18
tree46f9231f6460265d3e9921498a5bd4bf0e4573cd
parenta3fbe5f7e6e6095a5e1bb746b71586403b16e935
[Driver][gcov] Derive .gcno .gcda file names from -o and -dumpdir

Resolve a FIXME.
When -ftest-profile, -fprofile-arcs, or --coverage is specified and the
driver performs both compilation and linking phases, derive the .gcno &
.gcda file names from -o and -dumpdir.

`clang --coverage d/a.c d/b.c -o e/x && e/x` will now emit
`e/x-[ab].gc{no,da}` like GCC.

For -fprofile-dir=, we make the deliberate decision to not mangle the
input filename if relative.

The following script demonstrates the .gcno and .gcda filenames.

```
PATH=/tmp/Rel/bin:$PATH                # adapt according to your build directory
mkdir -p d e f
echo 'int main() {}' > d/a.c
echo > d/b.c

a() { rm $@ || exit 1; }

clang --coverage d/a.c d/b.c && ./a.out
a a-[ab].gc{no,da}
clang --coverage d/a.c d/b.c -o e/x && e/x
a e/x-[ab].gc{no,da}
clang --coverage d/a.c d/b.c -o e/x -dumpdir f/ && e/x
a f/[ab].gc{no,da}
clang --coverage -fprofile-dir=f d/a.c d/b.c -o e/x && e/x
a e/x-[ab].gcno f/e/x-[ab].gcda

clang -c --coverage d/a.c d/b.c && clang --coverage a.o b.o && ./a.out
a [ab].gc{no,da}
clang -c --coverage -fprofile-dir=f d/a.c d/b.c && clang --coverage a.o b.o && ./a.out
a [ab].gcno f/[ab].gcda

clang -c --coverage d/a.c -o e/xa.o && clang --coverage e/xa.o && ./a.out
a e/xa.gc{no,da}
clang -c --coverage d/a.c -o e/xa.o -dumpdir f/g && clang --coverage e/xa.o && ./a.out
a f/ga.gc{no,da}
```

The gcov code accidentally claims -c and -S, so -fsyntax-only -c/-S and
-E -c/-S don't leave to a -Wunused-command-line-argument warning. Keep
the unintended code for now.
clang/lib/Driver/ToolChains/Clang.cpp
clang/test/Driver/coverage.c
clang/test/Driver/working-directory.c