Issue |
138871
|
Summary |
[coverage] incorrect coverage when non-throwing code exists within a try block
|
Labels |
new issue
|
Assignees |
|
Reporter |
justincady
|
Code coverage reporting is incorrect for `try`/`catch` blocks where the contents of the `try` _cannot_ throw. Example:
```
// coverage.cc
#include <stdio.h>
#include <stdlib.h>
static __attribute__((noinline)) int do_throw(bool b) {
if (b) {
throw b;
}
return 1;
}
int main() {
int i = 0;
try {
i = 1;
} catch (...) {
abort();
}
printf("%s\n", __func__);
return i;
}
```
```
# build.sh
/usr/bin/clang++ --version | /bin/grep "clang version"
/usr/bin/clang++ -fprofile-instr-generate -fcoverage-mapping coverage.cc -o coverage
./coverage
/usr/bin/llvm-profdata merge -sparse default.profraw -o default.profdata
/usr/bin/llvm-cov show ./coverage -instr-profile=""
```
The coverage report incorrectly marks lines following `catch` as uncovered:
```
$ ./build.sh
clang version 21.0.0
main
1| |#include <stdio.h>
2| |#include <stdlib.h>
3| |
4| 0|static __attribute__((noinline)) int do_throw(bool b) {
5| 0| if (b) {
6| 0| throw b;
7| 0| }
8| 0| return 1;
9| 0|}
10| |
11| 1|int main() {
12| 1| int i = 0;
13| 1| try {
14| 1| i = 1;
15| 1| } catch (...) {
16| 0| abort();
17| 0| }
18| 0| printf("%s\n", __func__); // INCORRECT
19| 0| return i; // INCORRECT
20| 1|}
```
If the example is updated with a call that _may_ throw, everything works as expected:
```
$ ./build.sh
clang version 21.0.0
main
1| |#include <stdio.h>
2| |#include <stdlib.h>
3| |
4| 1|static __attribute__((noinline)) int do_throw(bool b) {
5| 1| if (b) {
6| 0| throw b;
7| 0| }
8| 1| return 1;
9| 1|}
10| |
11| 1|int main() {
12| 1| int i = 0;
13| 1| try {
14| 1| do_throw(false); // MAY THROW NOW
15| 1| } catch (...) {
16| 0| abort();
17| 0| }
18| 1| printf("%s\n", __func__); // CORRECT
19| 1| return i; // CORRECT
20| 1|}
```
Note that the mapping for `main` appears to be identical for both cases. First, for the non-throwing case:
```
$ clang++ -fprofile-instr-generate -fcoverage-mapping coverage.cc -o coverage -Xclang -dump-coverage-mapping
main:
File 0, 11:12 -> 20:2 = #0
File 0, 13:7 -> 15:4 = #0
File 0, 15:17 -> 17:4 = #2
Gap,File 0, 17:4 -> 18:3 = 0
File 0, 18:3 -> 19:11 = #1
[...]
```
And for the maybe throwing case:
```
$ clang++ -fprofile-instr-generate -fcoverage-mapping coverage.cc -o coverage -Xclang -dump-coverage-mapping
main:
File 0, 11:12 -> 20:2 = #0
File 0, 13:7 -> 15:4 = #0
File 0, 15:17 -> 17:4 = #2
Gap,File 0, 17:4 -> 18:3 = 0
File 0, 18:3 -> 19:11 = #1
[...]
```
Thus I _suspect_ this to be a problem with exception handling removal in codegen.
_______________________________________________
llvm-bugs mailing list
llvm-bugs@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs