Skip to content

[coverage] incorrect coverage when a do-while contains break or continue statements #139122

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
justincady opened this issue May 8, 2025 · 1 comment · Fixed by #139777
Closed
Assignees
Labels

Comments

@justincady
Copy link
Contributor

Code coverage reporting is incorrect for macros that contain statements such as break and continue:

// coverage.c
#include <stdio.h>

#define MY_MACRO()                                                             \
  do {                                                                         \
    int n = 0;                                                                 \
    if (n == 87) {                                                             \
      break;                                                                   \
    }                                                                          \
  } while (0)

static void func(void) {
  MY_MACRO();
  printf("Hello, World!\n");
}

int main(void) {
  MY_MACRO();
  func();
  return 0;
}
# build.sh
/usr/bin/clang++ --version | /bin/grep "clang version"
/usr/bin/clang++ -fprofile-instr-generate -fcoverage-mapping coverage.c -o coverage
./coverage
/usr/bin/llvm-profdata merge -sparse default.profraw -o default.profdata
/usr/bin/llvm-cov show ./coverage -instr-profile=default.profdata

The coverage report incorrectly marks lines following MY_MACRO() as uncovered:

$ ./build.sh
clang version 21.0.0
Hello, World!
    1|       |#include <stdio.h>
    2|       |
    3|       |#define MY_MACRO()                                                             \
    4|      2|  do {                                                                         \
    5|      2|    int n = 0;                                                                 \
    6|      2|    if (n == 87) {                                                             \
    7|      0|      break;                                                                   \
    8|      0|    }                                                                          \
    9|      2|  } while (0)
   10|       |
   11|      1|static void func(void) {
   12|      1|  MY_MACRO();
   13|      0|  printf("Hello, World!\n"); // INCORRECT
   14|      1|}
   15|       |
   16|      1|int main(void) {
   17|      1|  MY_MACRO();
   18|      0|  func();                    // INCORRECT
   19|      1|  return 0;
   20|      1|}

These region terminating statements trigger the incorrect coverage:

  • break
  • continue

But these region terminating statements do not appear to trigger the incorrect coverage:

  • return
  • goto
  • call to __noreturn__ function

Also, removing the break line from the example eliminates the incorrectly reported code coverage.

@justincady justincady self-assigned this May 9, 2025
justincady added a commit to justincady/llvm-project that referenced this issue May 13, 2025
The current region mapping for do-while loops that contain statements
such as break or continue results in inaccurate line coverage reports
for the line following the loop.

This change handles terminating statements the same way that other loop
constructs do, correcting the region mapping for accurate reports. It
also fixes a fragile test relying on exact line numbers.

Fixes llvm#139122
@justincady justincady changed the title [coverage] incorrect coverage when a macro contains break or continue statements [coverage] incorrect coverage when a do-while contains break or continue statements May 13, 2025
@justincady
Copy link
Contributor Author

I reduced this further; it does not require a macro. It's a problem with the handling of do-while loops:

#include <stdio.h>
int main(void) {
  do {
    int n = 0;
    if (n == 87) {
      break;
    }
  } while (0);
  printf("Hello, World!\n");
  return 0;
}

I posted a PR to address this issue.

justincady added a commit to justincady/llvm-project that referenced this issue May 19, 2025
The current region mapping for do-while loops that contain statements
such as break or continue results in inaccurate line coverage reports
for the line following the loop.

This change handles terminating statements the same way that other loop
constructs do, correcting the region mapping for accurate reports. It
also fixes a fragile test relying on exact line numbers.

Fixes llvm#139122
justincady added a commit that referenced this issue May 19, 2025
…#139777)

The current region mapping for do-while loops that contain statements
such as break or continue results in inaccurate line coverage reports
for the line following the loop.

This change handles terminating statements the same way that other loop
constructs do, correcting the region mapping for accurate reports. It
also fixes a fragile test relying on exact line numbers.

Fixes #139122
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant