<div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote gmail_quote_container"><div dir="ltr" class="gmail_attr">On Fri, Jul 10, 2026 at 1:33 PM Jonathan Wakely <<a href="mailto:jwakely@redhat.com">jwakely@redhat.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On Fri, 10 Jul 2026 at 12:25, Tomasz Kamiński <<a href="mailto:tkaminsk@redhat.com" target="_blank">tkaminsk@redhat.com</a>> wrote:<br>
><br>
> This implements remaining part of P2679R2, "Fixing std::start_lifetime_as<br>
> and std::start_lifetime_as_array".<br>
><br>
> For incomplete type _Tp, the is_implicit_lifetime_v<_Tp> check inside<br>
> start_lifetime_as already leads to following "invalid use of incomplete<br>
> type 'struct Incomplete'" error.<br>
><br>
> libstdc++-v3/ChangeLog:<br>
><br>
>         * include/bits/stl_construct.h (std::start_lifetime_as_array):<br>
>         static_assert that _Tp is complete type.<br>
>         * testsuite/std/memory/start_lifetime_as/neg.cc: New test.<br>
> ---<br>
> Testing on x86_64-linux. *start_lifetime* test already passed.<br>
> OK for trunk when all tests passes?<br>
<br>OK</blockquote><div>As start_lifetime_as_array compiled before with incomplete types, I do not</div><div>see a reason to backport this to 16. It would only break code that relies on that,</div><div>but it does not enable any new functionality.</div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">

<br>
><br>
>  libstdc++-v3/include/bits/stl_construct.h     |  8 ++++<br>
>  .../std/memory/start_lifetime_as/neg.cc       | 45 +++++++++++++++++++<br>
>  2 files changed, 53 insertions(+)<br>
>  create mode 100644 libstdc++-v3/testsuite/std/memory/start_lifetime_as/neg.cc<br>
><br>
> diff --git a/libstdc++-v3/include/bits/stl_construct.h b/libstdc++-v3/include/bits/stl_construct.h<br>
> index 4a0650f3cb8..9608d7fd8ca 100644<br>
> --- a/libstdc++-v3/include/bits/stl_construct.h<br>
> +++ b/libstdc++-v3/include/bits/stl_construct.h<br>
> @@ -346,6 +346,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION<br>
>      inline _Tp*<br>
>      start_lifetime_as_array(void* __p, size_t __n) noexcept<br>
>      {<br>
> +      static_assert(sizeof(_Tp), "template argument must be a complete type");<br>
> +<br>
>        auto __q = reinterpret_cast<_Tp*>(__p);<br>
>        if (!__n)<br>
>         return __q;<br>
> @@ -360,6 +362,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION<br>
>      inline const _Tp*<br>
>      start_lifetime_as_array(const void* __p, size_t __n) noexcept<br>
>      {<br>
> +      static_assert(sizeof(_Tp), "template argument must be a complete type");<br>
> +<br>
>        auto __q = reinterpret_cast<const _Tp*>(__p);<br>
>        if (!__n)<br>
>         return __q;<br>
> @@ -376,6 +380,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION<br>
>      inline volatile _Tp*<br>
>      start_lifetime_as_array(volatile void* __p, size_t __n) noexcept<br>
>      {<br>
> +      static_assert(sizeof(_Tp), "template argument must be a complete type");<br>
> +<br>
>        auto __q = reinterpret_cast<volatile _Tp*>(__p);<br>
>        if (!__n)<br>
>         return __q;<br>
> @@ -392,6 +398,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION<br>
>      inline const volatile _Tp*<br>
>      start_lifetime_as_array(const volatile void* __p, size_t __n) noexcept<br>
>      {<br>
> +      static_assert(sizeof(_Tp), "template argument must be a complete type");<br>
> +<br>
>        auto __q = reinterpret_cast<const volatile _Tp*>(__p);<br>
>        if (!__n)<br>
>         return __q;<br>
> diff --git a/libstdc++-v3/testsuite/std/memory/start_lifetime_as/neg.cc b/libstdc++-v3/testsuite/std/memory/start_lifetime_as/neg.cc<br>
> new file mode 100644<br>
> index 00000000000..1adbd2f266d<br>
> --- /dev/null<br>
> +++ b/libstdc++-v3/testsuite/std/memory/start_lifetime_as/neg.cc<br>
> @@ -0,0 +1,45 @@<br>
> +// { dg-do compile { target c++23 } }<br>
> +<br>
> +#include <bit><br>
> +#include <memory><br>
> +<br>
> +#include <testsuite_hooks.h><br>
> +#include <testsuite_allocator.h><br>
> +<br>
> +struct Incomplete;<br>
> +struct NonTrivial<br>
> +{<br>
> +  NonTrivial() {}<br>
> +  ~NonTrivial() {}<br>
> +};<br>
> +<br>
> +void test(void* p)<br>
> +{<br>
> +  (void)std::start_lifetime_as<Incomplete>(p);           // { dg-error "here" }<br>
> +  (void)std::start_lifetime_as_array<Incomplete>(p, 2);  // { dg-error "here" }<br>
> +  (void)std::start_lifetime_as<NonTrivial>(p);           // { dg-error "here" }<br>
> +  // Array are implicit-lifetime regardless of they element type<br>
> +  (void)std::start_lifetime_as_array<NonTrivial>(p, 2);<br>
> +<br>
> +  const void* cp = p;<br>
> +  (void)std::start_lifetime_as<Incomplete>(cp);           // { dg-error "here" }<br>
> +  (void)std::start_lifetime_as_array<Incomplete>(cp, 2);  // { dg-error "here" }<br>
> +  (void)std::start_lifetime_as<NonTrivial>(cp);           // { dg-error "here" }<br>
> +  (void)std::start_lifetime_as_array<NonTrivial>(cp, 2);<br>
> +<br>
> +  volatile void* vp = p;<br>
> +  (void)std::start_lifetime_as<Incomplete>(vp);           // { dg-error "here" }<br>
> +  (void)std::start_lifetime_as_array<Incomplete>(vp, 2);  // { dg-error "here" }<br>
> +  (void)std::start_lifetime_as<NonTrivial>(vp);           // { dg-error "here" }<br>
> +  (void)std::start_lifetime_as_array<NonTrivial>(vp, 2);<br>
> +<br>
> +  const volatile void* cvp = vp;<br>
> +  (void)std::start_lifetime_as<Incomplete>(cvp);           // { dg-error "here" }<br>
> +  (void)std::start_lifetime_as_array<Incomplete>(cvp, 2);  // { dg-error "here" }<br>
> +  (void)std::start_lifetime_as<NonTrivial>(cvp);           // { dg-error "here" }<br>
> +  (void)std::start_lifetime_as_array<NonTrivial>(cvp, 2);<br>
> +}<br>
> +<br>
> +// { dg-prune-output "invalid use of incomplete type" }<br>
> +// { dg-prune-output "template argument must be a complete type" }<br>
> +// { dg-prune-output "static assertion" }<br>
> --<br>
> 2.54.0<br>
><br>
<br>
</blockquote></div></div>