<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/138871>138871</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
[coverage] incorrect coverage when non-throwing code exists within a try block
</td>
</tr>
<tr>
<th>Labels</th>
<td>
new issue
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
justincady
</td>
</tr>
</table>
<pre>
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=default.profdata
```
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.
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJzsWFGP2jgQ_jXmZURkO4TAAw8su9z14VqpWql3T8hJBuLW2JHtQPn3JzvABhb2qt5W93IICeL5PB7PzDdjRzgnNxpxRrIHkj0OROtrY2dfW-elLkV1GBSmOswWpkIozQ6t2CBYbIz1Um9AOpC6NNZi6WFtLJAx9fZAxpTwJRnTUviyJmMKhTLlNwf7Gi2Cr4My7VF7B2Ydn88TYVUKrY1fga-t2Sfw9F1sG4UknRMav2N6_NJ5WIUvz5YlZRkHU6lL1VYIJF04X0mT1CR9uiVSsjjL6Nx54WUJq5Xw3sqi9bhaET4hfKKN1EpqJHxK-BSk9lCZVbSQ8ElhjIIiCEj-QOgcQK4hjPeHoNsQFCTtBkj-GH8t-tZqYN14N0roPKyxFVJHA3qatQcJJH0EelLk7aG3SidkvVUghiEYlCTJpUmiMNZ3K1yb1Vip_TrKOOGZI9lCx78LWK3WrS6Db86zjpuQF5voR-o6cCkUrVRV4uoujq2zhC-LsN9lqYTeEP5A-AMMhzu0ThoNJF_AGbKx2ADhPELhCAnmva1s3VizlgqHUjtvhxvUaIVHGK5POTTciqYJud1LKhia8yOh8yRofXm8Wk-p3XYYlqmEF7BFu0EYukZYh1DhWrTKJ0FsxT7o7Q-FGXcUlmYHrjZ76C8Ox20cN0XSx1vaLqPwXL9i8guH1QG2wn5zEHLdwdooZfbBGX0uCwetjiqwusPKUTSzF-CLMAFnCU0CMuZ3l4kshLf7kHzxBocDgr8N7rE6QNJLdDc4Og9Ski_ej_kA2YXmO7VgfAV6VR0A8ivIiZgAkyvJZQUJ49MLxHkmi_izE9iL08O_OxUHGL-A3axBwNJL0EVRYqMrDa_KFLDsCvJm4WLRfyfX3ahiwO66j12774crHRz7zYePi0-fPz8tno8Kp7fjEYohXH9uq-D0Yvc36-eHrlNi1w9D722bSnisYC99DQJKoRT4WnhYbcXh2EDDLnCH9uDrQOS9CfQWDvB7g6X_bxn877nLfhl32R3uvhNx2S3iTm8kwZm1V074ldz9R_L2vLgWyuElPf6Y_wXPv3_-9AU-fvry8-y-cPJriv8QwdnPEbzHTTa9HbO3yH2D2ndZ_dF47EgbyH06fBzP0jGioeU2DQrrwBsoEGSF2stSqAgrjK-hFA5dAktpnQ_bCoKgTxs9jJGKJxrh7h2jR_DOxyQY_tlVjGHVbpvh9bRT5YjWACylQqDBcMZIOmcchiR9Cq5L5zwmK-EpvYamJJ3nHZJlJJ2P7iKDlJ2geR_KI_Q30RC-6E3oMB1-QtJ5emQMnffVdpIONQ1LsJNaFryaPYTEzm4Efa6rc4i24lAg_B-kdw3Su0TpuW4dfICVa13olaGhyhMHBTTWFAq3XfPF7yU2PnTGWuhKBZ9b3JqdUCA1lKbCDepkUM3SappOxQBnLB-Nxzzjo2xQz9i0qqoxjouMjThdT0SaF-u1YONxmjMcpwM545RnNKM5S0d0lCXpGMs8x5GglDKGSEYUt0KqJNwWEmM3A-lcizOWTiY5GyhRoHLxls-5xj1EaaiB2ePAzuIVo2g3joyoks67FzVeehVfD5xvPNlj79J_TqV9jfqq3JgqnFaCuugkqUHEzhJfBgxaq2a1940L-RXr5kb6ui2S0myPt57ebeorlp7wZTTbEb487ms3438HAAD__yhhi7g">