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

    <tr>
        <th>Summary</th>
        <td>
            [[clang::unsafe_buffer_usage]] Source range in unsafe pointer arithmetic warning doesn't show entire unsafe operation
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            clang
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          tsepez
      </td>
    </tr>
</table>

<pre>
    Given a file range0.cc:
```
int lookup(int *ptr, unsigned idx) {
  return ptr[idx];
}

int* predecrement(int* ptr) {
  return --ptr;   // not actually useful, only for example
}
```
```
range0.cc:3:10:{3:10-3:13}: warning: unsafe buffer access [-Wunsafe-buffer-usage]
    3 |    return ptr[idx];
      |           ^~~
range0.cc:3:10: note: pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions
range0.cc:7:12:{7:12-7:15}: warning: unsafe pointer arithmetic [-Wunsafe-buffer-usage]
    7 |    return --ptr;   // not actually useful, only for example
      |             ^~~
```

The returned range indicates only the unsafe operand rather than the range of the unsafe operation.

We seek to automate applying the _Pragma("clang unsafe_buffer_usage begin")  / _Pragma("clang unsafe_buffer_usage end") form of suppression around the ranges as exactly indicated by the compiler,
and using some macro trickery,  i.e. 

```
#define UNSAFE_BUFFERS(...)                  \
  _Pragma("clang unsafe_buffer_usage begin") \
  __VA_ARGS__ \
  _Pragma("clang unsafe_buffer_usage end")

int lookup(int *ptr, unsigned idx) {
  return UNSAFE_BUFFERS(ptr)[idx];
}

int* predecrement2(int* ptr) {
  return --UNSAFE_BUFFERS(ptr);   // not actually useful, only for example
}
```

The ptr[idx]  looks unusual but does suppress the error.  The --ptr case, however gives

```
range1.cc:12:27: warning: unsafe pointer arithmetic [-Wunsafe-buffer-usage]
   12 |   return --UNSAFE_BUFFERS(ptr);   // not actually useful, only for example
      | ^~~
```

The returned range should cover the entire unsafe operation, not the unsafe argument allowing us to write

```
int lookup(int *ptr, unsigned idx) {
  return UNSAFE_BUFFERS(ptr[idx]);
}

int* predecrement(int* ptr) {
  return UNSAFE_BUFFERS(--ptr);   // not actually useful, only for example
}
```

which compiles cleanly

</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJy0ls1y2zYQx58GuuyIQ4GhKR10oGIrt04nbpqjBgKXJGoQ4OBDinrIs3eWpGXFilsncTkeEyKwu9gfdv-k8F41BnHN8g3Lb2cihta6dfDY49-zva1O6w_qgAYE1EojOGEaTBMpWVaytGQ36fSXlsoE0NY-xJ7xJf1gvOyDY_w9RDNEqUBVXxhfASs2LC0BHIboDNCqfENz-S3LaIoVt_R_cMp4Cb3DCqXDDun38vEpeb_yNp_T82wDAIxvGd-CsQGEDFFofYLosY6admWNPkFtHeAX0fUan-JeZHU5vkw-Y1m5SIlCsRnH8-GWkYushKNwRpmGhtF4USPsY12jAyEleg8s38w_jzPzcWYevWiQEFAyABmw4j0NXqQEwzWtmi6W3339-tJeiQTSvRfew7y-ij73sWnQB2WNh2DBoUR1QJC2QmiFq5CSgotVz0IVFIqPWMbxfLjlL2LprTKBuDgV2g6Dkq9gUzxj8ytn_j2KTxy_qYW0_KPFKSZWYzOAMpWSIqAfnYcWH1OzPTphaF1o0UFohRmmRztbX60loskY6DOCR3ygQxAx2E4EBNH3-kT8yW73uxNNJxhfMs6lFqaZXO1GZLsBGeyxUYZxTo1CbF5rh6aarGrrOtqsj33v0HtlDQhno6mekvEgPCGVQZ_OQCrYjzik7XqlkaSApSURiX4oI9shdEI6C8Ep-YDuRGcEKsEERgzf4OdZhbUyCJ9-uy-3d7vNp-327uM948skSYYEn18sfz-c8E_AOpvu_ix35ccP97vdj7o7Mzxr2U8K5FW-o_L9gGjy_1bNl4K8mZKO3XMpYzDw8BBN9FFo2McAlUV_rrWhfNA56xIAsh4aHaTwSHFbe8QDOmjUAf11wQyluRiFaRAlXrydBi34pBn_E8AnWXq9FPnWRl2BtIdBbqgCg3LXGkMhaScX-iNcE6lQQGhtj9SdcXgDHJ0KeI32jWv5XMgDrl_8ALiKML4d3raUj62S7aOyeZAahdEnlpazap1Vq2wlZrheFPkiW_FsVcza9Wq15wXmRS73hVjWWZZnYs_xZpnfZLISfKbWPOV5WqSLRZFniyKp0kKs5KrIb-qV5BWydyl2QulE60OXWNfMlPcR14t3N3mxmmmxR-2HL7lJlUh98tuZW5PBfB8bz96lWvngn1wEFfT0-bcZjbKSZeV39IzOJ7-FexudxPPL7196aGq0oaUN40WgAj2-VJSz6PS6DaH3tIPhkBoV2rhPpO0Y39KOp9u8d_YvlIHx7UDAM76dIBzW_J8AAAD__135W-c">