https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121128
Bug ID: 121128 Summary: Dereferencing std::indirect causes use-after-free on a valid code Product: gcc Version: 16.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: ykakeyama3014 at gmail dot com Target Milestone: --- The code below does not compile: #include <memory> constexpr int func() { std::indirect<int> x(42); return *std::move(x); } static_assert(func() == 42); GCC says: source.cpp:9:22: error: non-constant condition for static assertion 9 | static_assert(func() == 42); | ~~~~~~~^~~~~ source.cpp:9:19: in ‘constexpr’ expansion of ‘func()’ source.cpp:6:10: error: use of allocated storage after deallocation in a constant expression 6 | return *std::move(x); | ^~~~~~~~~~~~~ In file included from /opt/gcc-trunk/include/c++/16.0.0/memory:67, from source.cpp:1: /opt/gcc-trunk/include/c++/16.0.0/bits/allocator.h:200:52: note: allocated here 200 | return static_cast<_Tp*>(::operator new(__n)); | ~~~~~~~~~~~~~~^~~~~ libstdc++'s implementation of operator* unnecessarily creates temporary copy of __self, causing use-after-free. template<typename _Self> constexpr auto&& operator*(this _Self&& __self) noexcept { __glibcxx_assert(__self._M_objp != nullptr); return std::forward_like<_Self>(*((_Self)__self)._M_objp); } link: https://github.com/gcc-mirror/gcc/blob/4d6c3f3b4fbf8c2774848fcb36705ea5f0d514d4/libstdc%2B%2B-v3/include/bits/indirect.h#L285-L291 It should be written as: return std::forward_like<_Self>(*static_cast<_Self&&>(__self)._M_objp); Note that _M_objp's type i.e. _ATraits::pointer may not be a raw pointer type, so the value category should be propagated.