[gcc r17-2306] libstdc++: Mandate complete type for start_lifetime_as_array.

Tomasz Kaminski via Gcc-cvs <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
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" }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.