https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120348
Bug ID: 120348
Summary: Bogus line coverage triggered by passing pointers via
extern "C" functions
Product: gcc
Version: 16.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: gcov-profile
Assignee: unassigned at gcc dot gnu.org
Reporter: wentaoz5 at illinois dot edu
Target Milestone: ---
Hit the issue when measuring
https://sources.debian.org/src/lzma/9.22-2.2/CPP/7zip/Compress/LzmaDecoder.cpp/#L101
where RINOK is defined as:
#define RINOK(x) \
{ \
int __result__ = (x); \
if (__result__ != 0) \
return __result__; \
}
The direct output from gcov is:
-: 96: for (;;)
-: 97: {
6: 98: if (_inPos == _inSize)
-: 99: {
6: 100: _inPos = _inSize = 0;
9*: 101: RINOK(inStream->Read(_inBuf, _inBufSizeAllocated, &_inSize));
-: 102: }
A reduced reproducing step is given as follow:
$ gcc --version
gcc (GCC) 16.0.0 20250511 (experimental)
Copyright (C) 2025 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ cat > src1.cc << 'EOF'
int g;
extern "C" {
int foo(int *x);
}
int never;
void bar() {
int j = 0;
while (1)
{
g++;
if (never) {
g++;
return;
}
int l; // has to be local and in this scope
foo(&l);
j++;
if (j == 11)
return;
}
}
int main() {
for (int i = 0; i < 7; i++)
bar();
return 0;
}
EOF
$ cat > src2.c << 'EOF'
int foo(int *x) {
return 0;
}
EOF
$ rm -f *.gcov *.gcda *.gcno
$ g++ -c --coverage src1.cc
$ gcc -c --coverage src2.c
$ g++ --coverage src1.o src2.o -o prog
$ ./prog
$ gcov src1
$ cat src1.cc.gcov
-: 0:Source:src1.cc
-: 0:Graph:src1.gcno
-: 0:Data:src1.gcda
-: 0:Runs:1
-: 1:int g;
-: 2:
-: 3:extern "C" {
-: 4: int foo(int *x);
-: 5:}
-: 6:
-: 7:int never;
-: 8:
7: 9:void bar() {
7: 10: int j = 0;
-: 11: while (1)
-: 12: {
77: 13: g++;
77: 14: if (never) {
#####: 15: g++;
7*: 16: return;
-: 17: }
-: 18:
-: 19: int l; // has to be local and in this scope
77: 20: foo(&l);
-: 21:
77: 22: j++;
77: 23: if (j == 11)
7: 24: return;
70: 25: }
-: 26:}
-: 27:
1: 28:int main() {
8: 29: for (int i = 0; i < 7; i++)
7: 30: bar();
1: 31: return 0;
-: 32:}
where line coverage for line 16 is reported to be a nonzero value.
Tweaking the code format can produce what's closer to the original symptom
I experienced in lzma (although the first format seems more concerning):
-: 12: {
77: 13: g++;
84*: 14: if (never) { g++; return; }
-: 15: