<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/142203>142203</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            [coverage] macro with return statement leads to incorrect coverage
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            coverage
      </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 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|}
```
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJzclkuPo7gTwD-NcymBjEkgOXBIpyfS__JfKZo9rwwU4FmDkW2S6W-_snGTx6R3VjPSarQoB8ePerh-VS5ujGgHxIJsXsjmdcUn2yldfJmMFUPF67dVqeq34qBqhEqdUfMWQeOotBVDC8KAGCqlNVYWGqWh55VWBi7CdqD5BTTaSQ9gLLfY42ANSfeE-l9Gw4_uCTsSdlwUxJWfS2tsxIBw-vT599P___h0Ov12Imx75pKwHZDNgdA9uC8oWdZI-jLrEIOFnouBsK0bct1WhB2g6rgGwvZct-fZby8wfwkCReNkud1A0gNs85vlB2PYos4dJPlrGAWTaDDFz995_HgBKZSTkHVsuvk-JqMJO5bO9mMl-dAS9kLYC0TRGbURagCSH2DZ0mocgTDmt0LYQhj7jrBm1KoREiMxGKujFgfU3CJEzXssop6Powv1NTgQqeUfofvYCb3-fVAn5bmPnJaaWw496hYhMiPXBqHGhk_Sxm7ZwRKpuyl34gOBlTqD6dQFbpVD8CL4RNLXZ9Lug_C5-4brK9HyDXqu_zRgOwTpUGyUlOriroNk9AEFR0JGgRuYBi8S6w9gX3uzb-J9FzVIdnES5wGkxIV5_kh--OdJwZZzXsLzFHHL6b2CeXJ9d_oH02hzb8J3EgsAsvsDf5tq-bKXhtE1-bbfrN2no5vZuRWn5mlu_s8CH0fk2oAZsRKNqMCquboBfh354CNVYsUng54Pw3uHUo1z8eO-_JGMzqodGUsRdGUzIPZLEALvo3-dkp9FJHzBbvaAR_LjZCwqnuKxH2q46FAYXfA_ivPgV2dsAha1gksnJILSNzvx66jR-OByaRRoNJO07nV9J2Vmaym0vwI3i4RauRA9w8fdffCXsC11k_-RsvMTcD3halUXab1Ld3yFRZKvt1nKknW-6gq6wXWyq7KyyTjDesPyPKuwLCu2Rt406UoUjLIN3aQ02dEdzeMmSWiSY51vy6ysaiRrij0XMnYvZ6x0uxLGTFgka8ZoupK8RGl8_8fYghdjrhvUhX9ty6k1ZE2lMNZcpVhhpe8bl0Ob11vUH1s_kMhr48rotWV8P7qatCw6a0ffH_pusBW2m8q4Un149G-aiS-ucrKj98MQdgyunAv2VwAAAP__RGMEoQ">