1

I'm trying to use clang -coverage to generate coverage information for my C project, but all the function signatures are marked as not covered, when I'd expect them to be not instrumented at all.

Small example -- this file is hello.c:

extern int puts(const char*);

int main(int argc, char *argv[]) {
  puts("hello, world");
  return 0;
}

In this example, I'd expect lines 4 and 5 to be marked executable, but not line 3. I run clang -coverage and lcov like this to get initial coverage:

$ cc -coverage hello.c
$ lcov -c -i -d . -o coverage.base
Capturing coverage data from .
Found gcov version: 3.6.0
Found LLVM gcov version 3.4, which emulates gcov version 4.2
Scanning . for .gcno files ...
Found 1 graph files in .
Processing hello.gcno
Finished .info-file creation

The generated coverage file looks like this:

TN:
SF:/Users/isbadawi/cov/hello.c
FN:3,main
FNDA:0,main
FNF:1
FNH:0
DA:3,0
DA:4,0
DA:5,0
LF:3
LH:0
end_of_record

I'd expect the DA:3,0 line not to be there -- or at least, if it's there, I'd expect it to be marked covered in the final coverage report. When I go on to run a.out and run lcov again to generate a full coverage report, like this:

$ ./a.out
$ lcov -q -c -d . -o coverage.run
$ lcov -q -d . -a coverage.base -a coverage.run -o coverage.total

coverage.total looks like this:

TN:
SF:/Users/isbadawi/cov/hello.c
FN:3,main
FNDA:1,main
FNF:1
FNH:1
DA:3,0
DA:4,1
DA:5,1
LF:3
LH:2
end_of_record

I end up with 66.7% coverage instead of 100%. What am I doing wrong?

I'm using the system clang on OS X Yosemite:

Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn)
Target: x86_64-apple-darwin14.1.0
Thread model: posix

Trying the same thing with gcc (tried with 4.8.2), the line is still marked executable, but the final coverage report has it being executed.

Ismail Badawi
  • 36,054
  • 7
  • 85
  • 97

2 Answers2

0

The code the compiler generates doesn't always correspond directly with your lines of code. This may be the problem here. I experienced a similar frustration when LCOV would report no coverage on the closing brace of a block (function or otherwise), e.g.:

if (x < lim) {
  process_x(x);
  ++x_processed;
} // <== this line is listed as NOT COVERED

So, the way around it was to use LCOV keyword markers. In this case:

if (x < lim) {
  process_x(x);
  ++x_processed;
} // LCOV_EXCL_LINE

If you use the above marker on your line 3, that should fix your reporting issue.

int main(int argc, char *argv[]) {   // LCOV_EXCL_LINE

There are corresponding markers to exclude a range of lines, as well as excluding branch coverage for a line or range of lines. Check out the geninfo manpage for complete details. Here's an online version: http://ltp.sourceforge.net/coverage/lcov/geninfo.1.php

Note: These keywords can share the line with meaningful comments (i.e., they don't have to stand alone on the line in order to function properly).

Luv2code
  • 1,079
  • 8
  • 14
0

This bug should be fixed in Clang 8.

Marco Castelluccio
  • 10,152
  • 2
  • 33
  • 48