Open
Description
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|}