I generate coverage data and use an online service for visualization and CI. However I have strange "partials" (if-branches that are not fully covered). Looking at the gcov data it seems like an excessive amount of branches is detected.
An example:
function _ZNK5World8AdjustBQE5PointItEh15BuildingQuality called 415 returned 100% blocks executed 76%
415: 377:BuildingQuality World::AdjustBQ(const MapPoint pt, unsigned char player, BuildingQuality nodeBQ) const
-: 378:{
415: 379: if(nodeBQ == BQ_NOTHING || GetNode(pt).owner != player + 1 || !IsPlayerTerritory(pt))
branch 0 taken 95% (fallthrough)
branch 1 taken 5%
call 2 returned 100%
call 3 returned 100%
branch 4 taken 100% (fallthrough)
branch 5 taken 0% (throw)
branch 6 taken 85% (fallthrough)
branch 7 taken 15%
call 8 returned 100%
call 9 returned 100%
branch 10 taken 100% (fallthrough)
branch 11 taken 0% (throw)
branch 12 taken 17% (fallthrough)
branch 13 taken 83%
branch 14 taken 80% (fallthrough)
branch 15 taken 20%
branch 16 taken 95% (fallthrough)
branch 17 taken 5%
branch 18 taken 33% (fallthrough)
branch 19 taken 67%
branch 20 never executed
branch 21 never executed
branch 22 never executed
branch 23 never executed
call 24 never executed
It seems like the functions still get inlined and counted, although I'm already compiling with -g -O0 --coverage -fno-default-inline -fno-inline
. What can I do, so I only get the "meaningfull" data and inline-functions are attributed correctly at their definition?
I'm using g++-4.8 and gcov-4.8
Edit: If I split the if into its calls I get this:
415: 379: unsigned char owner = GetNode(pt).owner;
call 0 returned 100%
call 1 returned 100%
branch 2 taken 100% (fallthrough)
branch 3 taken 0% (throw)
call 4 never executed
415: 380: bool isPlayerTer = IsPlayerTerritory(pt);
call 0 returned 100%
call 1 returned 100%
branch 2 taken 100% (fallthrough)
branch 3 taken 0% (throw)
call 4 never executed
415: 381: if(nodeBQ == BQ_NOTHING || owner != player + 1 || !isPlayerTer)
branch 0 taken 95% (fallthrough)
branch 1 taken 5%
branch 2 taken 85% (fallthrough)
branch 3 taken 15%
branch 4 taken 17% (fallthrough)
branch 5 taken 83%
So the problem is really the calls. What can I do so those calls (and their branches(???)) don't get added to the coverage data?
Just found an artificial branch in the asm code that just checks a register and does a nop (besides a gcov counter increment) WTF?
0x0000000000d967de <World::AdjustBQ(Point<unsigned short>, unsigned char, BuildingQuality) const+340>: test %bl,%bl
0x0000000000d967e0 <World::AdjustBQ(Point<unsigned short>, unsigned char, BuildingQuality) const+342>: je 0xd967f5 <World::AdjustBQ(Point<unsigned short>, unsigned char, BuildingQuality) const+363>
0x0000000000d967e2 <World::AdjustBQ(Point<unsigned short>, unsigned char, BuildingQuality) const+344>: nop
0x0000000000d967e3 <World::AdjustBQ(Point<unsigned short>, unsigned char, BuildingQuality) const+345>: mov 0x1206c9e(%rip),%rax # 0x1f9d488 <__gcov0._ZNK5World8AdjustBQE5PointItEh15BuildingQuality+72>
0x0000000000d967ea <World::AdjustBQ(Point<unsigned short>, unsigned char, BuildingQuality) const+352>: add $0x1,%rax
0x0000000000d967ee <World::AdjustBQ(Point<unsigned short>, unsigned char, BuildingQuality) const+356>: mov %rax,0x1206c93(%rip) # 0x1f9d488 <__gcov0._ZNK5World8AdjustBQE5PointItEh15BuildingQuality+72>
0x0000000000d967f5 <World::AdjustBQ(Point<unsigned short>, unsigned char, BuildingQuality) const+363>: test %dl,%dl
I switched to clang++ and llvm-cov gcov
and got the correct results for this case (only 6 branches). However I also got some false positives at other places. One of the most disturbing ones seems to be a "function __cxx_global_array_dtor call" in the middle of a function on a line where similar lines (only integer parameters are changed) do not have this. So my current solution is to use gcov-4.8 without branch data as it is completely unreliable.