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

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

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|RESOLVED                    |REOPENED
         Resolution|FIXED                       |---

--- Comment #12 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Well, not fully.  The paper has additions of constexpr keywords on the library
side, but more importantly, we'll probably need some hacks in the compiler for
the library side, but waiting for Jonathan with that.

My understanding is that right now (perhaps that might change) placement new
should not be treated as constexpr function, but it needs to be in certain STL
templates (at least std::construct_at, something else?)

Also, I was afraid that in std::allocator<T>::allocate, the cast would be
reinterpret_cast, but apparently it isn't:

template <typename T>
constexpr T *
foo ()
{
  return static_cast<T *> (::operator new (sizeof (T)));
}

constexpr int
bar ()
{
  auto a = foo <int> ();
  ::operator delete (a);
  return 0;
}

constexpr auto p = bar ();

(this doesn't actually use placement new, because that does and should ATM
fail).  So, maybe it is just the placement new that needs to be handled.
But, if one can cast the global replaceable allocator function result to
anything in constexpr and our implementation triggers on the cast rather than
on some spot coming from the new operator, shouldn't we use some new C++
expression kind or say an internal function as an explicit cast in new
expression (placement or not) rather than any cast of the pointer?

Note, clang++ rejects the above testcase with
/tmp/6.C:16:16: error: constexpr variable 'p' must be initialized by a constant
expression
constexpr auto p = bar ();
               ^   ~~~~~~
/tmp/6.C:5:28: note: cannot allocate untyped memory in a constant expression;
use 'std::allocator<T>::allocate' to allocate memory of type 'T'
  return static_cast<T *> (::operator new (sizeof (T)));
                           ^
/tmp/6.C:11:12: note: in call to 'foo()'
  auto a = foo <int> ();
           ^
/tmp/6.C:16:20: note: in call to 'bar()'
constexpr auto p = bar ();
                   ^
1 error generated.

Is it correct or not?  The allocation function itself is not constexpr, on the
other side the wording says that the allocations should be elided in constexpr
contexts.

Reply via email to