From: Jakub Jelinek Date: Wed, 19 Nov 2025 08:38:17 +0000 (+0100) Subject: libstdc++: Implement proposed resolution of LWG4477 [PR122671] X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5294e0a0b40674365d8f9190fc1d9c456ea8c150;p=thirdparty%2Fgcc.git libstdc++: Implement proposed resolution of LWG4477 [PR122671] This patch implements the proposed resolution of https://cplusplus.github.io/LWG/issue4477 The PR complains that one can't successfully throw from constructor in placement new in a constant expression and catch that exception later on. The problem is while P2747R2 made placement ::operator new and ::operator new[] constexpr, when the ctor throws it invokes also these weird placement ::operator delete and ::operator delete[] which intentionally perform no action, and those weren't constexpr, so constant expression evaluation failed. 2025-11-19 Jakub Jelinek PR libstdc++/122671 * libsupc++/new (::operator delete, ::operator delete[]): Implement proposed LWG4477 resolution. Use _GLIBCXX_PLACEMENT_CONSTEXPR for placement operator deletes. * g++.dg/cpp26/constexpr-eh17.C: New test. --- diff --git a/gcc/testsuite/g++.dg/cpp26/constexpr-eh17.C b/gcc/testsuite/g++.dg/cpp26/constexpr-eh17.C new file mode 100644 index 00000000000..4d83d0d2cdd --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp26/constexpr-eh17.C @@ -0,0 +1,38 @@ +// PR libstdc++/122671 +// { dg-do compile { target c++26 } } + +#include +#include + +consteval auto +foo () +{ + struct E {}; + struct O + { + constexpr explicit O (int x) + { + if (x < 0) { throw E {}; } + } + }; + + try + { + struct S + { + O *s; + constexpr S () : s { std::allocator {}.allocate (1) } {} + constexpr ~S () { std::allocator {}.deallocate (s, 1); } + }; + + auto s = S {}; + + ::new (s.s) O { -1 }; + } + catch (E &) + { + } + return true; +} + +static_assert (foo ()); diff --git a/libstdc++-v3/libsupc++/new b/libstdc++-v3/libsupc++/new index fb36dae25a6..018adc0c4ed 100644 --- a/libstdc++-v3/libsupc++/new +++ b/libstdc++-v3/libsupc++/new @@ -229,15 +229,16 @@ void* operator new[](std::size_t, void* __p) _GLIBCXX_TXN_SAFE _GLIBCXX_USE_NOEXCEPT { return __p; } -#undef _GLIBCXX_PLACEMENT_CONSTEXPR - // Default placement versions of operator delete. -inline void operator delete (void*, void*) +_GLIBCXX_PLACEMENT_CONSTEXPR void operator delete (void*, void*) _GLIBCXX_TXN_SAFE _GLIBCXX_USE_NOEXCEPT { } -inline void operator delete[](void*, void*) +_GLIBCXX_PLACEMENT_CONSTEXPR void operator delete[](void*, void*) _GLIBCXX_TXN_SAFE _GLIBCXX_USE_NOEXCEPT { } + +#undef _GLIBCXX_PLACEMENT_CONSTEXPR + //@} } // extern "C++"