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

    <tr>
        <th>Summary</th>
        <td>
            [coverage] nested macro with unused branch leads to incorrect coverage
        </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 at the call site when a macro contains an unused branch. Example:

```
// macro.c
#include <stdio.h>

int enabled = 0;

#define MY_ID(x) 7

#define MY_LOG(fmt, ...)            \
  { \
    if (enabled) {                  \
      printf(fmt, ## __VA_ARGS__);  \
    }                               \
  }

int main(int argc, char *argv[]) {
  MY_LOG("%d, %s, %d\n",
 MY_ID(argc),
         "a",
         1);
}
```

```
# build-c.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 confusingly marks the `MY_LOG` usage in `main` as partially covered:

```
$ ./build-c.sh
clang version 19.1.7
    1|       |#include <stdio.h>
    2| |
    3|       |int enabled = 0;
    4|       |
    5|      0|#define MY_ID(x) 7
    6|       |
    7|       |#define MY_LOG(fmt, ...) \
    8|      1|  {                                 \
    9|      1| if (enabled) {                  \
   10|      0|      printf(fmt, ## __VA_ARGS__);  \
   11|      0|    }                               \
 12|      1|  }
   13|       |
   14|      1|int main(int argc, char *argv[]) {
   15|      1|  MY_LOG("%d, %s, %d\n",
   16|      1| MY_ID(argc),
   17|      0|         "a", // INCORRECT
   18|      0| 1);  // INCORRECT
   19|      1|}
```

If the example is updated to avoid using `MY_ID` withing `MY_LOG`, the problem disappears (even if the updated line has a branch):

```
$ ./build-c.sh
clang version 19.1.7
 1|       |#include <stdio.h>
    2|       |
    3|       |int enabled = 0;
    4|       |
    5|       |#define MY_ID(x) 7
    6|       |
    7| |#define MY_LOG(fmt, ...)            \
    8|      1|  { \
    9|      1|    if (enabled) {                  \
 10|      0|      printf(fmt, ## __VA_ARGS__);  \
   11|      0|    } \
   12|      1|  }
   13|       |
   14| 1|int main(int argc, char *argv[]) {
   15|      1|  MY_LOG("%d, %s, %d\n",
   16|      1|         enabled ? 1 : 2, // Now the entire MY_LOG usage is covered
   17|      1|         "a",
   18|      1|         1);
 19|      1|}
```

I suspect this is specific to macro expansion because I can substitute other constructs, including function calls, in the place of `MY_ID` and get correct results.

Also, I _believe_ the ideal behavior here is that all lines within `MY_LOG` usage in `main` should be covered; we _did_ execute that line and that's what usually happens. Then, appropriately, the `MY_LOG` implementation lines should be marked uncovered.
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJzMV1-P4jYQ_zTmZUSUOEDggQcWbk8rtXfS9VSpT8ixJ8RX40S2A7vfvpokwGaB6-21lRohkdjz5-fxzM9j4b3eWcQlmz6w6WYkmlBWbvmt8UFbKdTLKK_Uy3JdKQRZHdCJHYLDunJB2x1oD9rKyjmUAUSAUCJIYQx4HRCOJVoQsBfSVSArG4S2HoSFxjYeFeROWFlG8OFZ7GuDLF2xuP3N4v4Xrxh_ZPyxsxHJdiDVVppGIbB07YPSVVSy9EOnqm0AtCI3qIClG4hZ-tAb5anCQluEX__YPm0Ynz8zvoDsxuwvnz8yPi_2gfE1RFFEcq8eNl2zeAXAsofzO4AugPF575s0aPrqucgD1E7bUFw8MZ4ynsJ2-_tqu_ry8bftlvEFSx9ea7Fsc230pgeWbS4h2QttGZ_Tq3A7Sd5kKRwwvhJud-g2vwfdap-jwDhnfKo6fFPf_ys2Xdt2qnV2imhne9GPnhFxLi6ypyfpFkcYO6SvN_1tDqSQN9qosYx82SVF4x3jjzkt61EaYXcwHh_QeV1ZYBmB7Cd3DmuC0An1IgTnnpmidlWhDY619cGNd2jRiYAwLk4FMN6Luqb0Pw1EEsbV-YvFq4jMXT7fODLmsB-TFyWCgD26HcLY18J5BIWFaEyIaNqJI9l9PUQadwzK6gC-rI7w2jn0q-jXxNLNLWvD0H8tr2qdqrdovLY78wJ74f70bamzWdwnyiyGxpO8tjTa5tssBuGhFi5oYcxLZxPVnTKftLgH2zzYMkgWURJlfQoltMd9emXr73ACSfA2IbJT-qUD3TuMQbOToZNucHoejDvP91iFRGa3LGRvsX-feS7FPz8rdsu_yTB3CWcx1H4nXyXxYN3d208wWJJc2flhTkv4VQA2vdX0RqCTyUD8p3gQkukbn-9jRoBkNjRwjyuT7EaAB-wJ_Vn49Gn9-cuXD-uvveJ8qJicY35bfJgHN8n3qWjLG7tzmU75plYioIJQgThUWkFLBj0BPG2o1o86lJexjhQINVmqXZUb3IPSXtQ1Cufb5DugpTwkiZMDQ5VQCg-ibw_a1fxTxng_XbzJpX-NNK5K_j2k8SN0cbP2bzHHXWZ4bzPzH1PDZf5nyv9_VPmn55I4j5AAS1fwuro_Vceu-GzQ7rTLp8PVnw_Rt5yR3OaMK4oYyF16sB-jBfCNr6nVDyV1_h7oSxdaEi90bT4-18K21ZejFI1HeAIpLPgm90GHJiBUoURHHYUPrpGhjV9Xj0QfRWNlIH26R_RzHYcYIRGqYkA6wirYIfUn3R3EoW9M8FEHeGV8RRaeYJuj0XjAbWtKKxQGcizFQVcOSnRtbEMpAtDthUjI94T2902OL6vGKMjx0uE8wBFhq7TaAj6jpFW3xlt2I8z0xXjm4UjDjW_aDqkkcrQ-gq8lWgIu6tpVtdMioHk5kekAkCaG3qMNog1ah_yCiHo1VNDYHlo0UstULdKFGOEyySbZPE3jbDYql7M8VuksTmdyMVNqMpkXmEkU-aQo5nORTEZ6yWM-jac8SdIkSWaRkFmu-LTg88l8kogpm8S4F9pE1I5GlduNtPcNLpNJPF-kIyNyNL69aHJu8QjtLKXpdDNyy7aHzZudZ5PYaB_8xUzQwbQ31HNLPd2ARU_nRZd1tFXDWyUYFMpTXl4uqCf1UePMsgyh9nSytGW306Fs8khW-76dftWmf0MZGH9s4XrGH_v1HJb8rwAAAP__9nEdrA">