On 8/28/25 5:19 AM, Jakub Jelinek wrote:
On Thu, Aug 28, 2025 at 10:49:36AM +0200, Jason Merrill wrote:
I know, but P2590R2 is not implemented yet and as written in
https://gcc.gnu.org/PR106658 I have actually no idea what needs to be done
if anything on the compiler side.  Because at least the GIMPLE model
basically allows placement new anywhere without anything in the IL marking
up that the dynamic type has changed.  Though perhaps for constant
expression evaluation we want something...

Note this is fixed by PR121068 (r16-3022).

So, do you think for P2590R2 we want a purely library implementation which
does nothing (well, define the needed templates)?
Or do you prefer some builtin which will do nothing initially but might be
changed to do something when needed?
The first version actually clears the array, not sure if that is desirable
(especially for the const, volatile and const volatile overloads).

It seems undesirable: "The object representation
of a is the contents of the storage prior to the call to start_lifetime_as." https://eel.is/c++draft/obj.lifetime#3

So if we want to represent this somehow, it needs a different representation than the clobbers I used for placement new.

And we apparently even don't have std::is_implicit_lifetime trait.
Guess I should implement that first (C++23 P2674R1).  clang uses
__builtin_is_implicit_lifetime for that.

Sounds good.

void *operator new(__SIZE_TYPE__ __sz, void *__p) { return __p; }
void *operator new[](__SIZE_TYPE__ __sz, void *__p) { return __p; }
namespace std {
template <typename T>
[[nodiscard]] T* start_lifetime_as1(void* __p) noexcept
{
//  static_assert(__is_implicit_lifetime(T));
   auto __b = new (__p) unsigned char[sizeof(T)];
   auto __r = reinterpret_cast<T*>(__b);
   (void)*__r;
   return __r;
}
template <typename T>
[[nodiscard]] T* start_lifetime_as2(void* __p) noexcept
{
//  static_assert(__is_implicit_lifetime(T));
   return reinterpret_cast<T*>(__p);
}
}
struct S { int a; long long b; };
S *f1 (void *p) { return std::start_lifetime_as1<S>(p); }
S *f2 (void *p) { return std::start_lifetime_as2<S>(p); }
long double *f3 (void *p) { return std::start_lifetime_as1<long double>(p); }
long double *f4 (void *p) { return std::start_lifetime_as2<long double>(p); }

        Jakub


Reply via email to