Skip to content

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

@justincady

Description

@justincady

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.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions