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 <jakub@redhat.com>
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.
--- /dev/null
+// 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 ());
_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++"