On Fri, Jul 10, 2026 at 1:33 PM Jonathan Wakely <[email protected]> wrote:
> On Fri, 10 Jul 2026 at 12:25, Tomasz Kamiński <[email protected]> wrote: > > > > This implements remaining part of P2679R2, "Fixing std::start_lifetime_as > > and std::start_lifetime_as_array". > > > > For incomplete type _Tp, the is_implicit_lifetime_v<_Tp> check inside > > start_lifetime_as already leads to following "invalid use of incomplete > > type 'struct Incomplete'" error. > > > > libstdc++-v3/ChangeLog: > > > > * include/bits/stl_construct.h (std::start_lifetime_as_array): > > static_assert that _Tp is complete type. > > * testsuite/std/memory/start_lifetime_as/neg.cc: New test. > > --- > > Testing on x86_64-linux. *start_lifetime* test already passed. > > OK for trunk when all tests passes? > > OK As start_lifetime_as_array compiled before with incomplete types, I do not see a reason to backport this to 16. It would only break code that relies on that, but it does not enable any new functionality. > > > > > libstdc++-v3/include/bits/stl_construct.h | 8 ++++ > > .../std/memory/start_lifetime_as/neg.cc | 45 +++++++++++++++++++ > > 2 files changed, 53 insertions(+) > > create mode 100644 > libstdc++-v3/testsuite/std/memory/start_lifetime_as/neg.cc > > > > diff --git a/libstdc++-v3/include/bits/stl_construct.h > b/libstdc++-v3/include/bits/stl_construct.h > > index 4a0650f3cb8..9608d7fd8ca 100644 > > --- a/libstdc++-v3/include/bits/stl_construct.h > > +++ b/libstdc++-v3/include/bits/stl_construct.h > > @@ -346,6 +346,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > inline _Tp* > > start_lifetime_as_array(void* __p, size_t __n) noexcept > > { > > + static_assert(sizeof(_Tp), "template argument must be a complete > type"); > > + > > auto __q = reinterpret_cast<_Tp*>(__p); > > if (!__n) > > return __q; > > @@ -360,6 +362,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > inline const _Tp* > > start_lifetime_as_array(const void* __p, size_t __n) noexcept > > { > > + static_assert(sizeof(_Tp), "template argument must be a complete > type"); > > + > > auto __q = reinterpret_cast<const _Tp*>(__p); > > if (!__n) > > return __q; > > @@ -376,6 +380,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > inline volatile _Tp* > > start_lifetime_as_array(volatile void* __p, size_t __n) noexcept > > { > > + static_assert(sizeof(_Tp), "template argument must be a complete > type"); > > + > > auto __q = reinterpret_cast<volatile _Tp*>(__p); > > if (!__n) > > return __q; > > @@ -392,6 +398,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > inline const volatile _Tp* > > start_lifetime_as_array(const volatile void* __p, size_t __n) > noexcept > > { > > + static_assert(sizeof(_Tp), "template argument must be a complete > type"); > > + > > auto __q = reinterpret_cast<const volatile _Tp*>(__p); > > if (!__n) > > return __q; > > diff --git a/libstdc++-v3/testsuite/std/memory/start_lifetime_as/neg.cc > b/libstdc++-v3/testsuite/std/memory/start_lifetime_as/neg.cc > > new file mode 100644 > > index 00000000000..1adbd2f266d > > --- /dev/null > > +++ b/libstdc++-v3/testsuite/std/memory/start_lifetime_as/neg.cc > > @@ -0,0 +1,45 @@ > > +// { dg-do compile { target c++23 } } > > + > > +#include <bit> > > +#include <memory> > > + > > +#include <testsuite_hooks.h> > > +#include <testsuite_allocator.h> > > + > > +struct Incomplete; > > +struct NonTrivial > > +{ > > + NonTrivial() {} > > + ~NonTrivial() {} > > +}; > > + > > +void test(void* p) > > +{ > > + (void)std::start_lifetime_as<Incomplete>(p); // { dg-error > "here" } > > + (void)std::start_lifetime_as_array<Incomplete>(p, 2); // { dg-error > "here" } > > + (void)std::start_lifetime_as<NonTrivial>(p); // { dg-error > "here" } > > + // Array are implicit-lifetime regardless of they element type > > + (void)std::start_lifetime_as_array<NonTrivial>(p, 2); > > + > > + const void* cp = p; > > + (void)std::start_lifetime_as<Incomplete>(cp); // { dg-error > "here" } > > + (void)std::start_lifetime_as_array<Incomplete>(cp, 2); // { dg-error > "here" } > > + (void)std::start_lifetime_as<NonTrivial>(cp); // { dg-error > "here" } > > + (void)std::start_lifetime_as_array<NonTrivial>(cp, 2); > > + > > + volatile void* vp = p; > > + (void)std::start_lifetime_as<Incomplete>(vp); // { dg-error > "here" } > > + (void)std::start_lifetime_as_array<Incomplete>(vp, 2); // { dg-error > "here" } > > + (void)std::start_lifetime_as<NonTrivial>(vp); // { dg-error > "here" } > > + (void)std::start_lifetime_as_array<NonTrivial>(vp, 2); > > + > > + const volatile void* cvp = vp; > > + (void)std::start_lifetime_as<Incomplete>(cvp); // { > dg-error "here" } > > + (void)std::start_lifetime_as_array<Incomplete>(cvp, 2); // { > dg-error "here" } > > + (void)std::start_lifetime_as<NonTrivial>(cvp); // { > dg-error "here" } > > + (void)std::start_lifetime_as_array<NonTrivial>(cvp, 2); > > +} > > + > > +// { dg-prune-output "invalid use of incomplete type" } > > +// { dg-prune-output "template argument must be a complete type" } > > +// { dg-prune-output "static assertion" } > > -- > > 2.54.0 > > > >
