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

    <tr>
        <th>Summary</th>
        <td>
            [clang-tidy] `std::addressof` not checked by `clang-analyzer-core.StackAddressEscape`
        </td>
    </tr>

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

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

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

<pre>
    The code examples are all in C++23 (`-std=c++23`) and libc++ (`-stdlib=libc++ -fexperimental-library`).

---

Given a basic example:

```cpp
#include <iostream>
#include <memory>
#include <string>

auto f1()
{
    std::string a = "123";
    return std::addressof(a);
}

int main()
{
 auto result = f1();
    std::cout << *result;
}
```

It isn't caught by `clang-tidy`, and instead ASan catches it in runtime:

```
==270312==ERROR: AddressSanitizer: stack-use-after-scope on address 0x7f5177600020 at pc 0x557cec62fff6 bp 0x7ffcf239dcb0 sp 0x7ffcf239dca8
```

This is weird, given the fact that `__builtin_addressof` is checked by `clang-tidy` and (at least in `libc++`) `std::addressof` is simply a wrapper that calls `__builtin_addressof`.

Definition of `std::addressof`:

```cpp
template <class _Tp>
inline _LIBCPP_CONSTEXPR_SINCE_CXX17 _LIBCPP_NO_CFI _LIBCPP_HIDE_FROM_ABI _Tp* addressof(_Tp& __x) _NOEXCEPT {
  return __builtin_addressof(__x);
}
```

When changing the example to use `__builtin_addressof`:

```cpp
auto f1()
{
    std::string a = "123";
    return __builtin_addressof(a);
}
```

`clang-tidy` is able to figure out that it's returning a dangling pointer:

```
main.cpp:38: error: Address of stack memory associated with local variable 'a' returned to caller [clang-analyzer-core.StackAddressEscape,-warnings-as-errors]
```

---

This issue might be what caused `std::reference_wrapper` and `std::ranges::ref_view` to be unchecked, since (in libc++) they also used `std::addressof` in their constructors.

Example of faulty code utilizing `std::ranges::ref_view`:

```cpp
#include <iostream>
#include <ranges>
#include <vector>

auto f2()
{
    std::vector a{1, 2, 3};
    return a | std::ranges::views::filter([](auto &&_) { return _ > 1; });
}

int main()
{
    auto result = f2();
    for (auto &&e : result) {
 std::cout << e;
    }
}
```

`clang-tidy` doesn't catch it. ASan catches it (`stack-use-after-return`).

Example of faulty code utilizing `std::reference_wrapper`:
```cpp
#include <iostream>
#include <functional>
#include <string>

auto f3()
{
    std::string a = "123";
    return std::ref(a);
}

int main()
{
    auto result = f3();
 std::cout << result.get();
}
```

`clang-tidy` doesn't catch it. ASan catches it (`stack-use-after-return`).

---

More interestingly, if you implement your own reference wrapper that works similar to the one in libc++ by storing address, `clang-tidy` can detect the returning of dangling pointer/reference as long as `std::addressof` isn't used in constructor.

Definition of `Ref`:

```cpp
template<typename T>
struct Ref
{
    Ref(T &ref)
        : ptr(&ref)
    {}
    auto &get(this auto &&self) { return *self.ptr; }
private:
    T *ptr;
};
```

Faulty code utilizing `Ref`:

```cpp
#include <iostream>
#include <string>

auto f4()
{
    std::string a = "123";
    return Ref{a};
}

int main()
{
    auto result = f4();
 std::cout << result.get();
}
```

`clang-tidy` catches it:

```
main.cpp:28: error: Address of stack memory associated with local variable 'a' is still referred to by the stack variable 'result' upon returning to the caller.  This will be a dangling reference [clang-analyzer-core.StackAddressEscape,-warnings-as-errors]
```

But, when you change the constructor of `Ref` to use `std::addressof(ref)`, `clang-tidy` can no longer detect it, which leads to me thinking the case with `std::reference_wrapper` and `std::ranges::ref_view`.


</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzEWN1u2zwSfRr6ZmBDpmzJvvCF_7IbYL-2SAJs7wyaGtnc0qRAUnHcp1-QVGw5UdJm2-4HBI7En-HM8MzhoZi1YqcQZ2S8IONVj9Vur82sKM1jebCut9XFafawR-C6QMAndqgkWmAGgUkJQsGS0AWhC5oCoROSJX3rCpKu-HMzyRJCp8BUAVJsm-bWWCm2JF21uvolPlVoxAGVY7IvxdYwc4pmBiRZkWQef_v9fvv1H-IRFTDYMiv4s6sknbfHeCvhj1dV00JTobisCwSSLoW2ziA7kHTd1X3AgzanNzqtM0LtLp3hl9VOQzn04dJp05Ev4gMAQEjWnKTzOBsYkHQFhNIhTQmlJG2NNehqoy5TWFEYtFaXhE6YN_88mOSrtg9COTgwobqdCB4atLV0Ye2zs2mXm1zXftiSpEsgdB7ndSz8nOe2H7cOhFWE5g44q3d7B9sT-L2QTO36ThRxk5cBK0JZh6yA-T1TwJnje7QgnEecqZUThze3tnlNVyRd0TxJhzQ-r-_uPt-RdA7zmLd7poQT39H4NusY_9avLfZZ6dD0LdcVglbQJBmSp7wcD_M8S5KEJsAcVBySp_E458gzWpZlBtsqDCt5SdNpwbcJ2OsWNnknPQ97YUFYOKIwhU_DLgDa7RFKxh24PXM-XZvNthbSCbW5ACBL_Ey-R_4Ni660hpx6nDiQyGzII8mSS9k1ZUqypANf0bwVh0qegMHRsKpCEz3iTEr7tl9XFbvCUvikawW6fHOtH9asw0MlmQtVxyWzFjYP1bnwhJJCIWz-dbtYfvmyWX7-dP-w_vrlbnN_-2m53iy_fh3m595PnzfLm9vz6z9vV-vNzd3nvzbzxW2wSufQrrPQlMFm8-Sztfn0ef11uf7yAK2ibsq0Kx10Eif-ZMH8e48K-J6pnacGD4SG1cBpqC2-nfUfpvAP8FJ3wG8QU1e4rzArLLBtjLYUu9ogePYJqBOO0Nw2S0cHC6Z20j9WWigXyvodfvCEOPDpSOfpxDMAGqNNix48QgMrQGR9YNZqLpjDAo7C7UFqziQ8MiOCk4TmjNC8cQkL77WvDTRAxosYGFNMnr6j6XNtcHDvrTerrS1nFRK67B9ZCMj2me0HnywZv5e1F6dgwyK2RjiIwLEIx1intcXiqugMlmhQcdw0FX0mivYgpnZozxM2jwKPfpzT3nStGtLxhGWF4j4RE6FaZ70vFLfHEzBpA2yLd1gm8J0wwLWyztTcaWOvKGTdVIAuoWS1dKeoTGonpPjud_8nfP-9ouB5kc7OR_QhdIoC-uPii7OBkXwx9Amm_if1VdRRfwxIvoTO2H3czWMppK8NOomCz1eo94bQjNBsE46AfHEuaSDpGoYkXYBf9H-VGACvVQbtUBmlNnDtkM_hvJnX-NYM71QkeGXu4uPHaKfQeJYpju9BuMErGRL160vVENPWIVU_htqOsrxA9tfAWtaK-_OXyY-r2PSPqFiDv6Zfu8CVvgRXJ1rijMEO3Yvhfz9eXpD6X9oghEMNrRNqJ0-eCEQJJ12DV2XoL0v-zYA-Kjgj6FqqHbX5FmSckMx4AveSQitvun03257AOh03MpKzX-1V2JwpKNBhkKbYOop1-fospjcXn5gFqb1x-57cjBkNx4VQ7fPgfUV5hx-SkCRdulOFih0QHs6oj0uBt_UabXcBsA-eoQJ2p5euwDrpHCoXGPb1AG_oGVxn5BKaRQw6f3a32M-iLF8wMqFz3zrwKzSsHIxVRjyGcOYX497FeRx4wfX5uQvaN29x009m9UNU9A7TjH4n03jf8wW7Cv5XCWb0fyWYC4_8tKalv1XT-sufE1JGYjFR3G5Poe6jvfaU5-M6h7rSqkUMDeNEVTwACFr16O1usS3gL1TxR5Xzonae2I7-luWJNNy0MLp4oZsrXmldvDo_wzT1Hj9jdDKm0oH80Dxzp2icEHzvr-aF9WscvBtCfXu-93FmMe7Q79LvVyzaK2ZpMU2nrIezYT7MR0k6Tqa9_aycZMgKzAuWjMucpmmCWxxjPh2PsoKmWU_MaEJHSZakySQdjiaDKZ-Uk3GGwxHjjPIxGSV4YEIOpHw8DLTZ9cLlZDYdDadpT7ItShs-PlLaShalZLzqmZmf1N_WO0tGiRTW2YsZJ5wMny1b08art08UpV3nB5IfIitLerWRs71zVUgjvSH0Zifcvt4OuD4QeuN9av71K6P_g9wRehPitITexFAfZ_S_AQAA___ickJG">