https://gcc.gnu.org/bugzilla/show_bug.cgi?id=128295

            Bug ID: 128295
           Summary: Coverage counts __attribute__((assume)) as a branch, a
                    condition and a call that can never be covered
           Product: gcc
           Version: 16.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: gcov-profile
          Assignee: unassigned at gcc dot gnu.org
          Reporter: chfast at gmail dot com
                CC: chfast at gmail dot com
  Target Milestone: ---

int f(int n)
{
    __attribute__((assume(n <= 4)));
    return n * 2;
}
int main() { return f(3) - 6; }

$ g++ --coverage -fcondition-coverage -O0 -c t.cpp && g++ --coverage t.o &&
./a.out && gcov -b -g --conditions t.cpp

GCC 16.2 t.cpp.gcov:

        1:    1:int f(int n)
        -:    2:{
       1*:    3:    __attribute__((assume(n <= 4)));
branch  0 taken 0% (fallthrough)
branch  1 taken 100%
call    2 never executed
condition outcomes covered 1/2
condition  0 not covered (false)
        1:    4:    return n * 2;
        -:    5:}

The assumption is gimplified to if (n <= 4) ... else __builtin_unreachable (),
and the instrumentation counts that as a branch, a condition and a call. The
line is reported as partially executed, with a branch, a condition outcome and
a call that can only be covered by violating the assumption. The expression of
an assumption is not evaluated, so we expect no branch, condition or call on
this line.

The same with [[assume(n <= 4)]] (-std=c++23), with -fno-unreachable-traps, at
-Og, -O1 and -O2 (f noinline), and with GCC 15.2.

We hit this in intx (a multi-precision integer library), where lines with
assumptions keep branch and condition coverage below 100%.

Reply via email to