https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105327
Bug ID: 105327 Summary: Bogus use-after-free warning new in GCC 12 Product: gcc Version: 12.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: boris at kolpackov dot net Target Milestone: --- The following translation unit now (since 12.0) causes a bogus (AFAICS) use-after-free warning: $ cat <<EOF >use-after-free.cxx #include <memory> template <typename T> class pointer_traits; template <typename T> class pointer_traits<std::shared_ptr<T>> { public: static void* allocate (std::size_t n) { return operator new (n); } static void free (void* p) { operator delete (p); } }; template <typename T, typename P> class pointer_factory { public: static P create () { void* v (pointer_traits<P>::allocate (sizeof (T))); mem_guard g (v); P p (new (v) T); //g.release (); g.p_ = 0; return p; } private: struct mem_guard { mem_guard (void* p): p_ (p) {} ~mem_guard () {if (p_) pointer_traits<P>::free (p_);} void release () {p_ = 0;} void* p_; }; }; struct s {}; int main () { std::shared_ptr<s> p (pointer_factory<s, std::shared_ptr<s>>::create ()); } EOF $ g++ -Wall -Wextra -O3 -c -std=c++23 use-after-free.cxx In static member function ‘static void pointer_traits<std::shared_ptr<_Tp> >::free(void*) [with T = s]’, inlined from ‘pointer_factory<T, P>::mem_guard::~mem_guard() [with T = s; P = std::shared_ptr<s>]’ at use-after-free.cxx:42:52, inlined from ‘static P pointer_factory<T, P>::create() [with T = s; P = std::shared_ptr<s>]’ at use-after-free.cxx:36:3, inlined from ‘int main()’ at use-after-free.cxx:52:74: use-after-free.cxx:19:21: warning: pointer may be used after ‘void operator delete(void*, std::size_t)’ [-Wuse-after-free] 19 | operator delete (p); | ~~~~~~~~~~~~~~~~^~~ In file included from /home/boris/work/build2/tests/modules/gcc2/gcc-install/include/c++/12.0.1/bits/shared_ptr.h:53, from /home/boris/work/build2/tests/modules/gcc2/gcc-install/include/c++/12.0.1/memory:77, from use-after-free.cxx:1: In constructor ‘std::__shared_count<_Lp>::__shared_count(_Ptr) [with _Ptr = s*; __gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic]’, inlined from ‘std::__shared_count<_Lp>::__shared_count(_Ptr, std::false_type) [with _Ptr = s*; __gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic]’ at /home/boris/work/build2/tests/modules/gcc2/gcc-install/include/c++/12.0.1/bits/shared_ptr_base.h:928:22, inlined from ‘std::__shared_ptr<_Tp, _Lp>::__shared_ptr(_Yp*) [with _Yp = s; <template-parameter-2-2> = void; _Tp = s; __gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic]’ at /home/boris/work/build2/tests/modules/gcc2/gcc-install/include/c++/12.0.1/bits/shared_ptr_base.h:1469:17, inlined from ‘std::shared_ptr<_Tp>::shared_ptr(_Yp*) [with _Yp = s; <template-parameter-2-2> = void; _Tp = s]’ at /home/boris/work/build2/tests/modules/gcc2/gcc-install/include/c++/12.0.1/bits/shared_ptr.h:214:46, inlined from ‘static P pointer_factory<T, P>::create() [with T = s; P = std::shared_ptr<s>]’ at use-after-free.cxx:32:7, inlined from ‘int main()’ at use-after-free.cxx:52:74: /home/boris/work/build2/tests/modules/gcc2/gcc-install/include/c++/12.0.1/bits/shared_ptr_base.h:921:15: note: call to ‘void operator delete(void*, std::size_t)’ here 921 | delete __p; | ^~~~~~~~~~