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

    <tr>
        <th>Summary</th>
        <td>
            Presumably false positive clang-analyzer-cplusplus.NewDeleteLeaks in Clang-Tidy 17.0.1 for discarded resource-owning lambda closure rvalue
        </td>
    </tr>

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

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

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

<pre>
    When upgrading from Clang-Tidy 13 to 17, we noticed a new complaint about the following piece of code which – to the best of my knowledge – does not actually have a potential memory leak.

```c++
#include <memory>
#include <utility>

template <typename T1, typename T2>
static auto first_one(T1&& obj1, T2&& obj2)
{
    // const auto junk = std::forward<T2>(obj2);
    return std::forward<T1>(obj1);
}

int main()
{
    return first_one(
        [p = std::make_unique<int>(3)](){ return p ? *p : 1; },
        [q = std::make_unique<int>(7)](){ return q ? *q : 2; })();
}
```

Tool invocation and generated diagnostic:

```
$ /var/opt/llvm-17.0.1/bin/clang-tidy --extra-arg=-std=c++14 --extra-arg=-stdlib=libstdc++ /tmp/snippet.cxx
Error while trying to load a compilation database:
Could not auto-detect compilation database for file "/tmp/snippet.cxx"
No compilation database found in /tmp or any parent directory
fixed-compilation-database: Error while opening fixed database: No such file or directory
json-compilation-database: Error while opening JSON database: No such file or directory
Running without flags.
1 warning generated.
/tmp/snippet.cxx:13:12: warning: Potential leak of memory pointed to by field '_M_head_impl' [clang-analyzer-cplusplus.NewDeleteLeaks]
   13 |     return first_one(
      |            ^
/tmp/snippet.cxx:15:14: note: Calling 'make_unique<int, int>'
   15 |         [q = std::make_unique<int>(7)](){ return q ? *q : 2; })();
      |              ^~~~~~~~~~~~~~~~~~~~~~~~
/usr/lib64/gcc/x86_64-pc-linux-gnu/13.2.1/../../../../include/c++/13.2.1/bits/unique_ptr.h:1070:30: note: Memory is allocated
 1070 |     { return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); }
      |                              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/tmp/snippet.cxx:15:14: note: Returned allocated memory
   15 |         [q = std::make_unique<int>(7)](){ return q ? *q : 2; })();
      |              ^~~~~~~~~~~~~~~~~~~~~~~~
/tmp/snippet.cxx:13:12: note: Potential leak of memory pointed to by field '_M_head_impl'
   13 |     return first_one(
      |            ^
```
When uncommenting the `const auto junk = std::forward<T2>(obj2);` line, the warning goes away.

Interestingly, the diagnostic is *only* produced when using `-stdlib=libstdc++` but not when `-stdlib=libc++` is used. To analyze this further, I tried “reducing” the example by removing the `std::unique_ptr` dependency.

```c++
#include <utility>

template <typename T>
struct skimple_pointer
{
    simple_pointer() noexcept = default;
    explicit simple_pointer(T* const p) noexcept : m_pointer{p} {}
    ~simple_pointer() noexcept { delete m_pointer; }

    simple_pointer(const simple_pointer& other) = delete;
    simple_pointer& operator=(const simple_pointer& other) = delete;

    simple_pointer(simple_pointer&& other) noexcept : m_pointer{std::exchange(other.m_pointer, nullptr)}
    {
    }

    simple_pointer& operator=(simple_pointer&& other) noexcept
    {
        m_pointer = std::exchange(other.m_pointer, nullptr);
        return *this;
    }

    T& operator*() const { return *m_pointer; }
    T* operator->() const { return m_pointer; }

    explicit operator bool() const noexcept { return m_pointer; }

private:
    T* m_pointer{};
};

template <typename T, typename... Us>
auto make_simple(Us&&... args)
{
    return simple_pointer<T>(new T(std::forward<Us>(args)...));
}

template <typename T1, typename T2>
static auto first_one(T1&& obj1, T2&& obj2)
{
    // const auto junk = std::forward<T2>(obj2);
    return std::forward<T1>(obj1);
}

int main()
{
    return first_one(
        [p = make_simple<int>(3)](){ return p ? *p : 1; },
        [q = make_simple<int>(7)](){ return q ? *q : 2; })();
}
```

Same diagnostic is now shown regardless of `-stdlib` choice:

```
$ /var/opt/llvm-17.0.1/bin/clang-tidy --extra-arg=-std=c++14 /tmp/simplfied.cxx
Error while trying to load a compilation database:
Could not auto-detect compilation database for file "/tmp/simplfied.cxx"
No compilation database found in /tmp or any parent directory
fixed-compilation-database: Error while opening fixed database: No such file or directory
json-compilation-database: Error while opening JSON database: No such file or directory
Running without flags.
1 warning generated.
/tmp/simplfied.cxx:47:12: warning: Potential leak of memory pointed to by field 'm_pointer' [clang-analyzer-cplusplus.NewDeleteLeaks]
   47 |     return first_one(
      |            ^
/tmp/simplfied.cxx:49:14: note: Calling 'make_simple<int, int>'
   49 |         [q = make_simple<int>(7)](){ return q ? *q : 2; })();
      |              ^~~~~~~~~~~~~~~~~~~
/tmp/simplfied.cxx:35:30: note: Memory is allocated
   35 |     return simple_pointer<T>(new T(std::forward<Us>(args)...));
      |                              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/tmp/simplfied.cxx:49:14: note: Returned allocated memory
   49 |         [q = make_simple<int>(7)](){ return q ? *q : 2; })();
      |              ^~~~~~~~~~~~~~~~~~~
/tmp/simplfied.cxx:47:12: note: Potential leak of memory pointed to by field 'm_pointer'
   47 |     return first_one(
      |            ^
```
I don't think that there is a memory leak in this example either. I've tried looking at the implementation of `std::unique_ptr` and `std::make_unique` in `libc++` but failed to identify anything that I would have recognized as a significant difference that might cause or warrant the diagnostic from being not shown.

Clang-Tidy 13.0.1 was happy with either version of the code.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzsWd9v6rjy_2vclxGIOEDKQx8oHKTz1XfPXe12dR-RiQfwqWPn2E4p-7B_-9U4ARIK2_bcntVdaVEbQeL56ZnPjCfCe7UxiHdsdM9G8xtRha11d3nIi0d9s7Jyf_fvLRqoyo0TUpkNrJ0tYKaF2fQelNxDkkKwkGSMz2CHYGxQOUoQYHAHuS1KLZQJIFa2ChC2CGurtd0Rq1JhjmDXkFuJsNuqfAvsE2e3AzaJXGn5Cn2gNcUeHo3daZQbbK2SFj0JBZGHSmi9h614QhBQ2oAmKKGhwMK6PWgUj302mLPBtLmOB_Vfzvg9_dV3eapMriuJwNJZTcvST5ceVkFpFVpP4zUg2RziirAv0YgC4SEh_5x-8iORDyKoHEQVLKyV82FpDTJ-SxRjxsdgV18j8QM_3eCMTxqZWaM3AADjC8YXkFvjQ83xa2UegaVz8EGydMrS6dq6nXCSpbNaCX574Je2ODkMlTMXqZIjVdKmYtm87QXa80Iow_jtZV0bCW2TTw-jMaP7sqt6IR5xWRn1rUKWzpQJtSYpCRjNG0nZ_YE1US-A8Sl9mULC0nsgLfnshaBvbxKUXRH07SDoWxTEj4ImzdKXPjqEXttlD9ZqUObJ5iIoa0AYCRs06ERACVKJjbE-qJx0vBTGhxAdUhw8Ccf4wpaB8YXWT0UvyfqDfsL4YkWbsshjBgfK4F4Pn4MTPeE2LJ33ohfmTU4kwwuPtVqxdK7VygfZrCORoSgZX3ijyhJDP39-rhX65Jx1lN0aIbg9JX6woK0gkCCAULq2V4ogVsLj0b6ZrbSsk7sKticxYB4uksDaOliTBMb5RVU4r3l-sdcYVEaCMo0hYB0Is4dSODQBpHKYB0KCyGStnlH2Wnx6Ld2hbbAt0UTUJIq2hfDFgq_yba21decivnpr3iXh_37915f3CPilMpFup8KWoHmtxcY3-JjATrj49Bh_B-S85Nt0mqR04SS2oaSvPx8hmLA3gngNxaVVhmI6WFjtYa1QS2A8W_603KKQS1WUmvGMErMOU2GE3v-OrpeXuvL03_-CuzlqDPj_KB49ZeUhp5MUWDaDN2DMYdkRBz79uZEjugzJMmND9PFMaE1uYjx7iRl8BgfoyE7ajTpi_zrsuWhyNPqPy5-jLypPUKLVajxkfLHJc8YXz7fj5XjYK_OeVqZ67m1MxfgiSfs8Yky___LSFE7CnqbetghWKngSFe1elsH1t-TsQTZg6TQdtH3-Ux1DyoPQmrASZWMhLT9a2PLRiStLZ8uHsvYo9Sf0g99eqHLLqdv4et1yKeg7n_TJjEntUzhC-RW_nn-u-_ma298Ygr9EG6njOnijybK_c8i9gjEH2_9LgPlIyOgW4bpnNrktClKQSt4WgVrN727NxgPQivSZRV5HgKb-V-zEvtPafjYBHXqSrPcHklMHQcnD-NQaejiF0llZUdO-i2r7iGjjwZVST5qsqhDrciQ4X9papzxUHmUfHiw0IA5hqzysKxe26Ei1zxCcQnns6WcOZZVTCWluzKP2-CyKUiPtp8PCPrWcenRgK9HHA5BYopFo8v272_73dPatTt5VeQD_SOGFyzoG3YXW13cXxKQBY_E5xzLEkJC4FpUOnUzC51KrXIWX5A-0iXVklWesplAcF2b3JcvmBIwd8PrjFXWye5Cx0rZYtQHwT-yqdTq_PQZb7_2ksZWYd0y9QFFSG2IdS-ffyfdP1HzBqMPrqjePYYfP-VaYDWFFpOqfVvEZmEprikjC0Jbbuwe315157oO3KX1FHn2OSnZB6M3GpGf8GuRkfEoZ3nl8wbyHjkV82oRdvbOtYsP49HLYNUymRya9GjIvcnktco-5dWAGK2t1h1snId7AtnTqSYTTYeaobzuEiKZ9OOwG6xW8aQ0S-v0-_OaPCBTrSqzmdXQwfvubr0ODVjZ9zPXD-FlMpbOHU6v0cLlR-q3pki70SBfnAv9MRz54OtLe7h8xFLnC_wfPQn6lOOg2LMbuwG_tzoDDjXBSo_fU8rXaj_EA8q1VOf7FI5JTx0p-WiuU_xPjj44y_wxAPngA0vFuOh1mHzECaRXb751_DLOPm3-c2zh5dQLSQYqLE5Dh5PJx9EcBzXtOoa_Yn47eMY0ASEfnO_EjCuwV-84_rw8g3r_5r88e_sab3Uro7503tLP5I_OzW84-g7SG8SzQ0do8QtiK-KbNYQzL9vsvwvd4_j6cplHFHh8-M549YXMS19Y-Uk7XbCDuUoEm1BWjLrlXztzCyM7T9mhpPIjlZTzozghWhL1C6dp9SpKH13sqPmTOpjbnM-xiNYwv9xzmdmPU7xR4ZKBXG6PWKhexUK3X6NDkWBMWarMNkIvKxxqwE87RsrN5SHypuUISR_U2thmdoUHnhSd1CbATHraiLPexgDSOhCd0vnESicitxP6NvEvlJJ2IG7xLxpMs44PhJLnZ3snROBFyhKtxwpPROBmL0Ziv80GeYzYcTfBG3fEBT5NBMknSQZIm_dV4cJvL8TrB1TCZZBkbDrAQSvepf-lbt7lR3ld4N56MB_xGixVqH1_tcn7qZqgVGM1v3F1selbVxrPhQCsf_IlNUEHj3c8OfVWIld7DWmiPUFqvgnpCeGNdog1vuy42WLFbkcrnwkmU4NDbyuXYs7tYcbUoVlJArq2vHIJ7ErrCm8rpu20Ipae4io38RoVtterntmj6t0MbVzr7FXPq6qIzPOOL6I__BAAA__-zqleZ">