While updating my gcc compiler to gcc12.x version I came across some new warnings.
Consider this piece of code:
#include <memory>
struct Test
{
inline static int i = 0;
Test() { ++i; }
~Test() { --i; }
};
struct MHeap
{
template<typename T>
void manage()
{
using Td = std::remove_extent_t<T>;
std::shared_ptr<T> ptr(new T(), std::default_delete<Td[]>{});
}
};
int main()
{
MHeap mem;
mem.manage<Test[3]>();
}
$ g++ -O2 -Wall main.cpp
Error:
In member function 'void MHeap::manage() [with T = Test [3]]',
inlined from 'int main()' at <source>:24:25:
<source>:17:32: warning: pointer used after 'void operator delete [](void*, std::size_t)' [-Wuse-after-free]
17 | std::shared_ptr<T> ptr(new T(), std::default_delete<Td[]>{});
| ^~~~~~~
In file included from /opt/compiler-explorer/gcc-12.3.0/include/c++/12.3.0/memory:75,
from <source>:2:
In member function 'typename std::enable_if<std::is_convertible<_Up (*)[], _Tp (*)[]>::value>::type std::default_delete<_Tp []>::operator()(_Up*) const [with _Up = Test; _Tp = Test]',
inlined from 'std::__shared_count<_Lp>::__shared_count(_Ptr, _Deleter, _Alloc) [with _Ptr = Test*; _Deleter = std::default_delete<Test []>; _Alloc = std::allocator<void>; <template-parameter-2-4> = void; __gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic]' at /opt/compiler-explorer/gcc-12.3.0/include/c++/12.3.0/bits/shared_ptr_base.h:958:11,
inlined from 'std::__shared_count<_Lp>::__shared_count(_Ptr, _Deleter) [with _Ptr = Test*; _Deleter = std::default_delete<Test []>; <template-parameter-2-3> = void; __gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic]' at /opt/compiler-explorer/gcc-12.3.0/include/c++/12.3.0/bits/shared_ptr_base.h:939:57,
inlined from 'std::__shared_ptr<_Tp, _Lp>::__shared_ptr(_Yp*, _Deleter) [with _Yp = Test; _Deleter = std::default_delete<Test []>; <template-parameter-2-3> = void; _Tp = Test [3]; __gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic]' at /opt/compiler-explorer/gcc-12.3.0/include/c++/12.3.0/bits/shared_ptr_base.h:1478:17,
inlined from 'std::shared_ptr<_Tp>::shared_ptr(_Yp*, _Deleter) [with _Yp = Test; _Deleter = std::default_delete<Test []>; <template-parameter-2-3> = void; _Tp = Test [3]]' at /opt/compiler-explorer/gcc-12.3.0/include/c++/12.3.0/bits/shared_ptr.h:232:48,
inlined from 'void MHeap::manage() [with T = Test [3]]' at <source>:17:28,
inlined from 'int main()' at <source>:24:25:
/opt/compiler-explorer/gcc-12.3.0/include/c++/12.3.0/bits/unique_ptr.h:132:11: note: call to 'void operator delete [](void*, std::size_t)' here
132 | delete [] __ptr;
| ^~~~~~~~~~~~~~~
Is this warning valid ?
Compiler: GCC 12
Interestingly using a array of size less than 3 i.e mem.manage<Test[2]>()
clears the warning.
(Don't have enough reputation to comment heh) Following on Remy's answer and Artyer's comment, one can see on godbolt that the warning disappears if one slightly refactors the code:
using Td = std::remove_extent_t<T>;
auto p = new T;
std::shared_ptr<T> ptr(p, std::default_delete<Td[]>{});
I'm not sure why this happens.