https://gcc.gnu.org/bugzilla/show_bug.cgi?id=122671

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
   Last reconfirmed|                            |2025-11-18
     Ever confirmed|0                           |1
                 CC|                            |redi at gcc dot gnu.org
             Status|UNCONFIRMED                 |NEW

--- Comment #1 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
To me this testcase looks to be invalid, but I think most likely undesirably
so.
The wg21.link/P2747R2 paper made placement operator new constexpr.
At that time constexpr exceptions weren't in C++26, so that was all that was
needed.
But later on when wg21.link/P3068R5 was voted in, the P2747R2 changes look
insufficient.
The problem is that when you throw from constructor during operator new, it
invokes placement operator delete.  And P2747R2 didn't touch that, see
http://eel.is/c++draft/new.delete.placement
and
http://eel.is/c++draft/new.syn
If I change in preprocessed source the
--- pr122671.ii 2025-11-18 12:05:55.474736993 +0100
+++ pr122671.ii 2025-11-18 12:17:23.568904481 +0100
@@ -282,10 +282,10 @@ void* operator new[](std::size_t, void*
   noexcept
 { return __p; }

-inline void operator delete (void*, void*)
+constexpr void operator delete (void*, void*)
   noexcept
 { }
-inline void operator delete[](void*, void*)
+constexpr void operator delete[](void*, void*)
   noexcept
 { }

then it compiles fine.
So, I think a LWG issue for this should be filed and make those placement
operator deletes constexpr in C++26 too.

Testcase with some formatting cleanups for the testsuite:
#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 ());

Reply via email to