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

    <tr>
        <th>Summary</th>
        <td>
            [clang-tidy] `bugprone-unhandled-self-assignment` doesn't know about allocator arguments to copy/move constructors
        </td>
    </tr>

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

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

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

<pre>
    I may have copy/move constructors that take an additional allocator argument (similar to `vector( const vector& other, const Allocator& alloc );`). Additionally, the type may use the [leading-allocator convention](https://en.cppreference.com/w/cpp/memory/uses_allocator.html) with `std::allocator_arg_t`.

If I call one of these "extended" copy/move constructors in my copy/move-and-swap idiom, `bugprone-unhandled-self-assignment` doesn't recognize it and produces a false positive warning (copy-and-swap/move should not trigger the warning).

A rough test:

```
// REQUIRES: static-analyzer
// RUN: clang-tidy -checks='-*,bugprone-unhandled-self-assignment' %s -- | FileCheck %s

namespace std {
  namespace pmr {
    template <typename TYPE = void>
    class allocator {};
  }

  struct allocator_arg_t {} allocator_arg;
};

#define LEADING_STYLE 1

class MyValueType
{
  // pointer member to trigger bugprone-unhandled-self-assignment
  void *foo = nullptr;

  public:
    using allocator_type = std::pmr::allocator<>;

 MyValueType(const MyValueType& other)
    {
    }

#ifdef LEADING_STYLE
    MyValueType(std::allocator_arg_t, const allocator_type& alloc, const MyValueType& other)
    {
    }
#else
    MyValueType(const MyValueType& other, const allocator_type& alloc)
    {
 }
#endif

#ifdef LEADING_STYLE
    // CHECK-NOT: warning
 MyValueType& operator=(const MyValueType& other)
    {
        MyValueType tmp(std::allocator_arg, get_allocator(), other);
        swap(tmp);
 return *this;
    }
#else
    // CHECK-NOT: warning
    MyValueType& operator=(const MyValueType& other)
    {
        MyValueType tmp(other, get_allocator());
        swap(tmp);
        return *this;
 }
#endif

    void swap(MyValueType& other) noexcept {
    }

 allocator_type get_allocator() const {
        return allocator_type();
 }
};
```


</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJy0Vt1u4zYTfRr6ZiBDoSzZvvCF4p_vC7qbtrvZFnsV0OJIYkORAkk56336gpIs2YbTzRZoECAOOTw8c87MmMxaUSjEFYnvSbyZsMaV2qw-ihf8E6VEM9lrflw9QMWOULIDQqbrI6G7SreflXWmyZw2FlzJHDj2gsAUMM6FE1oxCUxKnTGnDTBTNBUqB4QurKiEZAacBpKEB_QYhC46SDj9n4B2JRpC1_1GegLzey0yELok0T1JQkKXU0iHi-XRH3MlgjvW2CbQWGwXSHwvkXGhimBkl2l1QOXPknhD6KJ0rrYkSgndEbpDNc3q2mCOBlWG00xXhO5eCd1lde31wEobL0xj0T4PqNPSVZLQJbwKV_pMreMeM0qHkGdmimdHknBKwpSE6UMOD5AxKUErBJ17xhaBUIrfHCqOnFD6tg1CQXU83w6Y4oF9ZTUILjzrteexb4raaIVBo0qmuEQeWJR50BWEd4kkIXCNVhE6d2Aw04US3xGEA6Y41EbzJkMLDHImLUKtrXDigPDKjBKq8C57GsP9J7q21I3koLQDZ0RRoGlN6Y95FzshUjC6KUpwaJ3XrF30Pne_Ye8MfNr-_uXh0_YziVKwjjmRBUwxefyO5izoy6PfzyRTReAEP0KQlZi9WBJtCJ0HhKaErt-hCp0DobGFIAAyX8NOSFx7oHa146hYhbZmGYJ1HMj8noQpwLhaV2ZYBXBY1ZI5BBKtfaX6OHj6-tsWSLSBgxacRNs-NpPM2rOO8ijzjS9_v-8_tgQAunqAqyLr4y-Xu9MDTCtZxDEXCuHDNt08PP7v-fPT1w9buOu2OxIfj38w2eDTscb2eE-hU7vWQjk0UGG1x7bJT06_Q2GP49MGQtNc61YG1UhZOzNQBKibvRRZVxdemsb6mhsza5veHx06rq7MVeuRaO21HUDPc_LF6yfOxdowj5b9raONg_iERiLnmF-K10dd3vDmMBjm3WU-w9AbA36SHo1QWrxJ5p_wfkjn6sLxNsVF_g5d-rpZ_3-7_iV4_PXJ9-ppIFwbk4Cu0XT-bX7ap6vEwVX1m074xAt04zgndOEx6XrEj86BuzG3aDFPWwZdY5QvZlcKO8bfcuQHMlx79l8oMTh-M_F35Nv_3Ez7Vl344Lbde7A36IPS-C3D2t3queu-v8G9r-DL9HuS12W9GLPprxim4_nXT5hO-Criy2jJJri6m8d3dJ7MF3RSrmaL_V2MfB7zJA6TfRTm82wfR7NsGeWzfBlNxIqGNA6TKAyXs4TS6R3dJ0nMkEVhtlgiJ7MQKybkVMpDNdWmmAhrG1zdzZKIziaS7VHa9tlG6fitRij1zziz8qeCfVNYMgulsM6OOE442T74zo7Fm3_zKHhR-hXYXjfuxivP-rH_1jNl0hi5unxhFcKVzb5_WHmy_Z-gNvovzByhu1YBS-iuF-Gwon8HAAD__54pXgY">