<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">