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

    <tr>
        <th>Summary</th>
        <td>
            Multiple clang-tidy use-after-move checks do not catch use-after-forward with non-move() rvalue ref at callsite
        </td>
    </tr>

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

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

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

<pre>
    Neither bugprone-use-after-move nor clang-analyzer-cplusplus.Move catch use-after-forward if the caller of the perfect-forwarding function doesn't explicitly do `std::move()`, even if the perfect-forwarding function is still forwarding an rvalue. bugprone-use-after-move doesn't actually evaluate std::forward at all (bug 82023), so that's unsurprising, but the analyzer does catch this if the caller is providing `T&&` instead of `T`. Example:
```
#include <cassert>
#include <concepts>
#include <utility>

struct S {
  constexpr S() = default;
  constexpr S(S&& other) { other.live = false; }

  bool live = true;
};

constexpr void consume(S s) {}

template <typename T>
constexpr void forward(T&& t) {
  static_assert(std::same_as<S, T>);
  assert(t.live);
  consume(std::forward<T>(t));
 assert(!t.live);              // (technically a use-after-forward also)
 consume(std::forward<T>(t));  // use-after-forward
}

int main() {
#if 1  // Setting to 0 causes clang-analyzer-cplusplus.Move to fire
 forward(S());
#else
  S s;
 forward(std::move(s));
#endif
}
```
Live repro: https://godbolt.org/z/M579Yn5aM
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJyUVUFz4jgT_TXi0gVlpADm4ENChtOX78Jc9jQly22sHVlySS0mzK_fkm1swiZTtSnHYFr9uvv1c7cMQZ8tYsE2L2zzupCRGueL7qcMpO15UbrqWvwfNTXooYznzjuLyxhwKWtCv2zdBcE6D8pIe15KK831N_ql6kwM6X_1lk4oSaqB2a12_pf0FegaqElmY9CDG5469DUquh3S9gx1tIq0s1A5DJbxHQG-d0YrTeYKlQO2zQJVTDwz8ZxyYjxnfM-2GeMHwAvaW6g_gesAgbQxcGeUFvxFmoirL8ufc5KKojTmCphcJCFMSd0qlgTSGGA8L-MZcp5xkRLlBwgOqJHE-C5AtCH6zuug7TnZykh99jd--5gjq9To8ECkDtB5d9F9BWybfWd8m65tBtoGQlklrnvDNlvBt3fZdgZTotkry54TbcM1PHKhrTKxQmDioGQI6ImJb59anVXYUfjCHEkbTdfZ2t8D-agITsB2L8MvAMqlRN87D6ehl8DEK1RYy2iIiS_OnYZCwSW99k67l-FhZfQFe4xamoBMvADbvd5nAVA6Z2A6Rz7iFCidnb739znwxemqzyO2SXcnCGPkhwCEbWeSKJg40LVDK1uE7xMXD4CjYBjPx-4B3WDHdANJ0urH2A-eT1oLssUfMjBxOCXx9CH4_o60yYV6Wj4a50oexcvEYcDKqdfsndeEyPj6HhQ-_DF-ZPyYxE-oGqtV_7LITwaDNMElhAH9v6U0xfkX7NzLu7ZoS9BKbW8yuxGclFvDekI7IaWRCOQgAyVjSG_gH6ceOai1x7GIuaGjou8JZFxgkuXYg6ShidvZ8XHEhU9QbKXrxzo_vs__Swr32HnHxDM0RF1IqH2VZ1eVztDK-TPjx9-MH982u_1fdiPfFlUhqr3YywUW612Wr9eZEPtFU1S5EHmebflG5jss5XorOC_zpx2qfSXKcqELnvGnjK-36322EfmqWsu8zusM92W1VojsKcNWarMy5tKm2AsdQsQijcd8YWSJJvQbivOBcdLVlXGeNpYvktOyjOfAnjKjA4UZhjQZLN6iId0ZhNkZHma4alD9DGmTWEdfrqtfmhqwzi7nFTNuB_BYp9meFB004SJ6UzxQq6mJ5Uq5lvFjynD8WHbe_Y2KGD_2VQfGj33h_wQAAP___c1ZyA">