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" }

Reply via email to