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++"

Reply via email to