<html>
    <head>
      <base href="https://bugs.llvm.org/">
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW - NewDeleteLeaks reports false positive with shared_ptr"
   href="https://bugs.llvm.org/show_bug.cgi?id=45514">45514</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>NewDeleteLeaks reports false positive with shared_ptr
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>clang
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>unspecified
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>PC
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>All
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>enhancement
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>Static Analyzer
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>dcoughlin@apple.com
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>pavel.kryukov@phystech.edu
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>dcoughlin@apple.com, llvm-bugs@lists.llvm.org
          </td>
        </tr></table>
      <p>
        <div>
        <pre>Created <span class=""><a href="attachment.cgi?id=23345" name="attach_23345" title="NewDeleteLeaks false positive">attachment 23345</a> <a href="attachment.cgi?id=23345&action=edit" title="NewDeleteLeaks false positive">[details]</a></span>
NewDeleteLeaks false positive

In the example attached, memory leak is reported while passing std::shared_ptr
around factory-like methods.

Command line. Note -std=c++17 and -O3 options, without them nothing is reported

<span class="quote">> $ clang++-10 --analyze -Xanalyzer -analyzer-output=text -std=c++17 -O3 example.cpp</span >

Output:

example.cpp:26:5: warning: Potential leak of memory pointed to by field '_M_pi'
    return get_D_or_C(config);
    ^
example.cpp:26:12: note: Calling 'get_D_or_C'
    return get_D_or_C(config);
           ^~~~~~~~~~~~~~~~~~
example.cpp:19:12: note: Assuming 'val' is true
    return val ? get_D() : get_C();
           ^~~
example.cpp:19:12: note: '?' condition is true
example.cpp:19:18: note: Calling 'get_D'
    return val ? get_D() : get_C();
                 ^~~~~~~
example.cpp:12:11: note: Calling 'make_shared<D, >'
   return std::make_shared<D>();
          ^~~~~~~~~~~~~~~~~~~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/shared_ptr.h:721:14:
note: Calling 'allocate_shared<D, std::allocator<D>, >'
      return std::allocate_shared<_Tp>(std::allocator<_Tp_nc>(),
             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/shared_ptr.h:705:14:
note: Calling constructor for 'shared_ptr<D>'
      return shared_ptr<_Tp>(_Sp_alloc_shared_tag<_Alloc>{__a},
             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/shared_ptr.h:359:4:
note: Calling constructor for '__shared_ptr<D, __gnu_cxx::_S_atomic>'
        : __shared_ptr<_Tp>(__tag, std::forward<_Args>(__args)...)
          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/shared_ptr_base.h:1342:14:
note: Calling constructor for '__shared_count<__gnu_cxx::_S_atomic>'
        : _M_ptr(), _M_refcount(_M_ptr, __tag, std::forward<_Args>(__args)...)
                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/shared_ptr_base.h:675:19:
note: Calling
'__allocate_guarded<std::allocator<std::_Sp_counted_ptr_inplace<D,
std::allocator<D>, __gnu_cxx::_S_atomic> >>'
          auto __guard = std::__allocate_guarded(__a2);
                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/allocated_ptr.h:97:21:
note: Calling 'allocator_traits::allocate'
      return { __a, std::allocator_traits<_Alloc>::allocate(__a, 1) };
                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/alloc_traits.h:436:16:
note: Calling 'new_allocator::allocate'
      { return __a.allocate(__n); }
               ^~~~~~~~~~~~~~~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/ext/new_allocator.h:101:2:
note: Taking false branch
        if (__n > this->max_size())
        ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/ext/new_allocator.h:105:2:
note: Taking false branch
        if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
        ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/ext/new_allocator.h:111:27:
note: Memory is allocated
        return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp)));
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/alloc_traits.h:436:16:
note: Returned allocated memory
      { return __a.allocate(__n); }
               ^~~~~~~~~~~~~~~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/allocated_ptr.h:97:21:
note: Returned allocated memory
      return { __a, std::allocator_traits<_Alloc>::allocate(__a, 1) };
                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/shared_ptr_base.h:675:19:
note: Returned allocated memory
          auto __guard = std::__allocate_guarded(__a2);
                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/shared_ptr_base.h:1342:14:
note: Returning from constructor for '__shared_count<__gnu_cxx::_S_atomic>'
        : _M_ptr(), _M_refcount(_M_ptr, __tag, std::forward<_Args>(__args)...)
                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/shared_ptr.h:359:4:
note: Returning from constructor for '__shared_ptr<D, __gnu_cxx::_S_atomic>'
        : __shared_ptr<_Tp>(__tag, std::forward<_Args>(__args)...)
          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/shared_ptr.h:705:14:
note: Returning from constructor for 'shared_ptr<D>'
      return shared_ptr<_Tp>(_Sp_alloc_shared_tag<_Alloc>{__a},
             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/shared_ptr.h:721:14:
note: Returned allocated memory
      return std::allocate_shared<_Tp>(std::allocator<_Tp_nc>(),
             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
example.cpp:12:11: note: Returned allocated memory
   return std::make_shared<D>();
          ^~~~~~~~~~~~~~~~~~~~~
example.cpp:19:18: note: Returned allocated memory
    return val ? get_D() : get_C();
                 ^~~~~~~
example.cpp:26:12: note: Returned allocated memory
    return get_D_or_C(config);
           ^~~~~~~~~~~~~~~~~~
example.cpp:26:5: note: Potential leak of memory pointed to by field '_M_pi'
    return get_D_or_C(config);
    ^
1 warning generated.</pre>
        </div>
      </p>


      <hr>
      <span>You are receiving this mail because:</span>

      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>