https://gcc.gnu.org/g:5294e0a0b40674365d8f9190fc1d9c456ea8c150
commit r16-5411-g5294e0a0b40674365d8f9190fc1d9c456ea8c150 Author: Jakub Jelinek <[email protected]> Date: Wed Nov 19 09:38:17 2025 +0100 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 <[email protected]> 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: --- gcc/testsuite/g++.dg/cpp26/constexpr-eh17.C | 38 +++++++++++++++++++++++++++++ libstdc++-v3/libsupc++/new | 9 ++++--- 2 files changed, 43 insertions(+), 4 deletions(-) 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 000000000000..4d83d0d2cddc --- /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 <new> +#include <memory> + +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 <O> {}.allocate (1) } {} + constexpr ~S () { std::allocator <O> {}.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 fb36dae25a6d..018adc0c4ede 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++"
