https://gcc.gnu.org/g:7fa4a7d62fb895088e387457654a8e5c61983157
commit r17-2306-g7fa4a7d62fb895088e387457654a8e5c61983157 Author: Tomasz Kamiński <[email protected]> Date: Fri Jul 10 13:17:13 2026 +0200 libstdc++: Mandate complete type for start_lifetime_as_array. 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. Reviewed-by: Jonathan Wakely <[email protected]> Signed-off-by: Tomasz Kamiński <[email protected]> Diff: --- libstdc++-v3/include/bits/stl_construct.h | 8 ++++ .../testsuite/std/memory/start_lifetime_as/neg.cc | 45 ++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/libstdc++-v3/include/bits/stl_construct.h b/libstdc++-v3/include/bits/stl_construct.h index 4a0650f3cb8d..9608d7fd8caa 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 000000000000..bdd504cf41c4 --- /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 "incomplete type" } +// { dg-prune-output "template argument must be a complete type" } +// { dg-prune-output "static assertion" }
