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

    <tr>
        <th>Summary</th>
        <td>
            `__attribute__((pure))`/`__attribute__((const))` is a massive unchecked footgun
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            new issue
      </td>
    </tr>

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

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

<pre>
    This originates from https://oss-fuzz.com/testcase-detail/5834828872548352

Consider (somewhat reduced from the original source):
```
#include <vector>

std::vector<int> handle() {
  std::vector<int> v(42, 42); // this somehow leaks
  return v;
}

__attribute__((pure)) // double yikes
std::vector<int> footgun(int argc) {
  std::vector<int> v(24, 24);
  if(argc != 42)
    throw int(0); // yikes
  return v;
}

int main(int argc, char* argv[]) {
    try {
        auto v = handle();
        auto v2 = footgun(argc);
    } catch(...) {}
    return 0;
}
```
https://godbolt.org/z/zdavdKnfa

Not a single diagnostic is triggered by this.
Yet this is completely broken.

In oss-fuzz issue, this manifested as an obscure leak,
exception got optimized away, so this took a bit to understand...

```
    // 'const', 'pure' and 'noalias' attributed functions are also nounwind.
    if (TargetDecl->hasAttr<ConstAttr>()) {
      FuncAttrs.addAttribute(llvm::Attribute::ReadNone);
      FuncAttrs.addAttribute(llvm::Attribute::NoUnwind);
      // gcc specifies that 'const' functions have greater restrictions than
      // 'pure' functions, so they also cannot have infinite loops.
      FuncAttrs.addAttribute(llvm::Attribute::WillReturn);
    } else if (TargetDecl->hasAttr<PureAttr>()) {
      FuncAttrs.addAttribute(llvm::Attribute::ReadOnly);
      FuncAttrs.addAttribute(llvm::Attribute::NoUnwind);
      // gcc specifies that 'pure' functions cannot have infinite loops.
      FuncAttrs.addAttribute(llvm::Attribute::WillReturn);
```

Which means functions with these attributes *can* can call non-returning functions,
or functions that throw exceptions, but the exception must be handled within the function.
Yet we fail to catch that at all, even in UBSan.

I think at least 3 things are missing:
* we should infer `nothrow` attribute (and manifest in AST!) upon seeing `const`/`pure`.
  that would catch the simplified snippet: https://godbolt.org/z/nM6PM6Msc
* we lack `willthrow` clang attribute. (maybe also `maythrow`?)
  * we should add it, infer it from `throw` stmts
  * and propagate it in obvious cases through call stack
* we should diagnose calls to `willthrow` functions from `nothrow` functions :)

CC @AaronBallman @regehr 
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzFV99v2zYQ_mvkFyKGLNmy8-AHJ2mBYmtXdC2KPQWUdJY406QhUvacv37fUbItJ9mCYtgWKLIpHY_f3X33w7ktj8uvtXLCNqpSRnpyYt3Yrai937koXUXJe1zWuZt1-_Q0LuwWS0j5Qjq6KclLpfFktkini2SxmCez6SKdJVH8EMWr7n5vjVMlNSJKFs5u6VBLLxoq24LK7jBf0wmAFs62TUFRcsund2qyuL-6ZZIqU-i2JBGl93sqvG2i9N3wSOdL3p2uTm_vlfGQEbU0pYbyBfSLaH7XiQvxlxv2kJ0mUXIv-A5Md6JzCUDDbWxPbQ9Ck9y4k7KGfNsYbE17_dH8YYju8VF636i89fT4GLAsdm0TTGZUnfrStrkmcVQbcm8YtbbWV62BGjwQsqmKH7EumbJ1fL89AxZCrfGKVQHPJEofevP7twLWNzCb1SSL-NoxA8hv-4IRb6W6Bn8vilo2UbLi9T6a3UWzh2cmAUFzvH7Af7L1VuwFAx6GemDYUC4Jghf39a67kgZeUUhf1Hg_Ho9PME5WsEhvY_yKjdfMvU6qypa51X5smwqrJ_4v5b78yazl0EOfLNwinDIV6FAqWRnrvCoE2AcSVRUhlUR-DHwcd1t-I9_RExcydqfJkz6KvLEbMuOh8g9GnHIbwq4ldn7YupVGrZHnUC6dkJDLXQGWBqpDqttPfxS088oaUQGmxdeteuItB3lkVc522ry1G1iRKwCzojUoB84jQOzRAZxn_gr-70gVJfMCdQR0m7NefHQpMwe0kpfGSq2kC09O2YXy0pqC4cECQJcaeIxtzUHh6MsZas216SvCT_6BCn2D3KilW0EPcoXrl---v-vp9JyLQrzHQSzjxrIsVycAENd6v-2S7_I0LL-QLD9ZQy_p-eO6PtlvwaaXunr3VUUh3I4KtVao8J4r8MCjAzfVck-iagidoAGxHY7p32CTeUXzIBJnLefI07HzeSGNAT-CcmXWyigPIlm7c-N_Zvh3pfWXkH6v5S1pR28E9zOw_zux_cXo4_8Y2xdB-a-D8Lxrh_v3WhW12JIEnguyg_I1swXROueugxErQOYugA_8a43cNTddtUU5vOJbp942A63BE12fOpepQE2oDyPHpXhtW-dFTn3PKAMgZYLQSd-gtB7wFGMPV7LQGbqT-NKa9dOeDDwsvt39Kp-VW66GZsOyKKM4Mw0Pqq48bVGBsbjMPTAdZ7natrrkkPEMlcUIIhuFbxdvMcW5EJ6qNh-_-vUr927wud3BRkfETsO2Lu0RGPAniwNRsvjMgWDMIRx5sg4YFLoIE6wUzqjdjjA-rMRb_cx8zD5_zD664soeLYsNwziANmdLCi0B7mzPmA3aymPeF22IYHWSjtL3g2Hk2k0grVCew9A5DB0nzJjYdj7M-a13w-3sul1jd7JC3eMtivvdXtmW08aFtGpsW9UdDdG6is1rMerbMwUx7nov7LzQ84RqEM7Ly-DU26spGk1vGq9kY80dlCPQvG6ooroRI1pOsmw-myTxLB6Vy7S8TW_lyCuvaQnNfztxnpnwilTfIXoxnickOAaaooYAbE3FhrtsN0GN2kYvn3ECidTm_c-GUEC6jxt4-3cMo1iGscOF3xDz28WoXsqFnKzTWTGjbJqUk3le5gnNyzmVi2yymGUjLXNU9iXPhUli6HCaXBKMiSO1TOIkmUziNJlM52k8npZlnpGMsyRL83SdwGuEiVOPGQeTddQsA6S8rRxeauW8u7xkYytDtOzG0BEmx9o2y58pp5L2Xz6MwuHLAP5P-5kYBg">