Skip to content

[coverage] macro with return statement leads to incorrect coverage #142203

Open
@justincady

Description

@justincady

Code coverage reporting is incorrect for macros with raw return statements:

// coverage.c
#define RETURN_ERROR(val) \
     return (val);

int main(int argc, char *argv[]) {
    if (argc < 87) {
        RETURN_ERROR(2);
    }
    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 the line following RETURN_ERROR() as uncovered:

$ ./build.sh
clang version 19.1.7
    1|       |#define RETURN_ERROR(val) \
    2|      1|     return (val);
    3|       |
    4|      1|int main(int argc, char *argv[]) {
    5|      1|    if (argc < 87) {
    6|      1|        RETURN_ERROR(2);
    7|      0|    }
    8|      0|    return 0;
    9|      1|}

It appears specific to macro expansion because the same code with a raw return statement is correct:

$ ./build.sh
clang version 19.1.7
    1|       |#define RETURN_ERROR(val) \
    2|       |     return (val);
    3|       |
    4|      1|int main(int argc, char *argv[]) {
    5|      1|    if (argc < 87) {
    6|      1|        return 2;
    7|      1|    }
    8|      0|    return 0;
    9|      1|}

And wrapping the return statement in the macro with a do while or statement expression also results in correct code coverage:

$ ./build.sh
clang version 19.1.7
    1|       |#define RETURN_ERROR(val) \
    2|      1|     do { return (val); } while (0)
    3|       |
    4|      1|int main(int argc, char *argv[]) {
    5|      1|    if (argc < 87) {
    6|      1|        RETURN_ERROR(2);
    7|      1|    }
    8|      0|    return 0;
    9|      1|}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions