This implements remaining part of the P3726R2, "Adjustments to Union
Lifetime Rules", by using std::start_lifetime in inplace_vector::_M_init.

The alternative branch no longer uses std::start_lifetime_as, that was
preventing optimizations (see PR124121), it is not required as GCC treats
any write to union as potentially changing active member Further when
available __builtin_constexpr_diag is used to emit better error message.
TODO comment is also removed, as suggested new call is not supported until
clang 23.

libstdc++-v3/ChangeLog:

        PR libstdc++/125845
        PR libstdc++/124121
        * include/bits/version.def (start_lifetime): Move before
        inplace_vector.
        (constexpr_inplace_vector): Define.
        * include/bits/version.h: Regenerate.
        * include/std/inplace_vector (__cpp_lib_constexpr_inplace_vector):
        Define.
        (inplace_vector::_M_init): Use std::start_lifetime instead of
        std::start_lifetime_as, when available. Emit error using
        __builtin_constexpr_diag.
        * testsuite/23_containers/inplace_vector/cons/1.cc: Enable and
        andd compile time tests for non-trivial types.
        * testsuite/23_containers/inplace_vector/copy.cc: Likewise.
        * testsuite/23_containers/inplace_vector/modifiers/assign.cc:
        Likewise.
        * testsuite/23_containers/inplace_vector/modifiers/erase.cc:
        Likewise.
        * testsuite/23_containers/inplace_vector/modifiers/multi_insert.cc:
        Likewise.
        * testsuite/23_containers/inplace_vector/modifiers/single_insert.cc:
        Likewise.
        * testsuite/23_containers/inplace_vector/move.cc: Likewise.
        * testsuite/23_containers/inplace_vector/version.cc: Test value of
        __cpp_lib_constexpr_inplace_vector.
---
Tested on x86_64-linux. All *inplace_vector* test also passed in
all standard modes. OK for trunk?

Should we backport the changes to alternative branch (removing
start_lifetime_as) to GCC-16?

 libstdc++-v3/include/bits/version.def         | 27 ++++--
 libstdc++-v3/include/bits/version.h           | 30 ++++---
 libstdc++-v3/include/std/inplace_vector       | 22 +++--
 .../23_containers/inplace_vector/cons/1.cc    | 90 ++++++++-----------
 .../23_containers/inplace_vector/copy.cc      | 18 +---
 .../inplace_vector/modifiers/assign.cc        |  9 +-
 .../inplace_vector/modifiers/erase.cc         |  7 +-
 .../inplace_vector/modifiers/multi_insert.cc  | 14 +--
 .../inplace_vector/modifiers/single_insert.cc |  9 +-
 .../23_containers/inplace_vector/move.cc      | 33 ++-----
 .../23_containers/inplace_vector/version.cc   | 12 +++
 11 files changed, 120 insertions(+), 151 deletions(-)

diff --git a/libstdc++-v3/include/bits/version.def 
b/libstdc++-v3/include/bits/version.def
index 3f314ffe1ee..36f8c9c31cf 100644
--- a/libstdc++-v3/include/bits/version.def
+++ b/libstdc++-v3/include/bits/version.def
@@ -2315,6 +2315,15 @@ ftms = {
   };
 };
 
+ftms = {
+  name = start_lifetime;
+  values = {
+    v = 202603;
+    cxxmin = 26;
+    extra_cond = "__has_builtin(__builtin_start_lifetime)";
+  };
+};
+
 ftms = {
   // 202406 P0843R14 inplace_vector
   // 202603 P3981R2 Better return types in std::inplace_vector and 
std::exception_ptr_cast
@@ -2326,6 +2335,15 @@ ftms = {
   };
 };
 
+ftms = {
+  name = constexpr_inplace_vector;
+  values = {
+    v = 202502;
+    cxxmin = 26;
+    extra_cond = "__glibcxx_start_lifetime";
+  };
+};
+
 ftms = {
   name = indirect;
   values = {
@@ -2665,15 +2683,6 @@ ftms = {
   };
 };
 
-ftms = {
-  name = start_lifetime;
-  values = {
-    v = 202603;
-    cxxmin = 26;
-    extra_cond = "__has_builtin(__builtin_start_lifetime)";
-  };
-};
-
 // Standard test specifications.
 stds[97] = ">= 199711L";
 stds[03] = ">= 199711L";
diff --git a/libstdc++-v3/include/bits/version.h 
b/libstdc++-v3/include/bits/version.h
index 16b7425269a..e79ea5043d7 100644
--- a/libstdc++-v3/include/bits/version.h
+++ b/libstdc++-v3/include/bits/version.h
@@ -2561,6 +2561,16 @@
 #endif /* !defined(__cpp_lib_modules) */
 #undef __glibcxx_want_modules
 
+#if !defined(__cpp_lib_start_lifetime)
+# if (__cplusplus >  202302L) && (__has_builtin(__builtin_start_lifetime))
+#  define __glibcxx_start_lifetime 202603L
+#  if defined(__glibcxx_want_all) || defined(__glibcxx_want_start_lifetime)
+#   define __cpp_lib_start_lifetime 202603L
+#  endif
+# endif
+#endif /* !defined(__cpp_lib_start_lifetime) */
+#undef __glibcxx_want_start_lifetime
+
 #if !defined(__cpp_lib_inplace_vector)
 # if (__cplusplus >  202302L)
 #  define __glibcxx_inplace_vector 202603L
@@ -2571,6 +2581,16 @@
 #endif /* !defined(__cpp_lib_inplace_vector) */
 #undef __glibcxx_want_inplace_vector
 
+#if !defined(__cpp_lib_constexpr_inplace_vector)
+# if (__cplusplus >  202302L) && (__glibcxx_start_lifetime)
+#  define __glibcxx_constexpr_inplace_vector 202502L
+#  if defined(__glibcxx_want_all) || 
defined(__glibcxx_want_constexpr_inplace_vector)
+#   define __cpp_lib_constexpr_inplace_vector 202502L
+#  endif
+# endif
+#endif /* !defined(__cpp_lib_constexpr_inplace_vector) */
+#undef __glibcxx_want_constexpr_inplace_vector
+
 #if !defined(__cpp_lib_indirect)
 # if (__cplusplus >  202302L) && _GLIBCXX_HOSTED
 #  define __glibcxx_indirect 202502L
@@ -2954,14 +2974,4 @@
 #endif /* !defined(__cpp_lib_hardened_view_interface) */
 #undef __glibcxx_want_hardened_view_interface
 
-#if !defined(__cpp_lib_start_lifetime)
-# if (__cplusplus >  202302L) && (__has_builtin(__builtin_start_lifetime))
-#  define __glibcxx_start_lifetime 202603L
-#  if defined(__glibcxx_want_all) || defined(__glibcxx_want_start_lifetime)
-#   define __cpp_lib_start_lifetime 202603L
-#  endif
-# endif
-#endif /* !defined(__cpp_lib_start_lifetime) */
-#undef __glibcxx_want_start_lifetime
-
 #undef __glibcxx_want_all
diff --git a/libstdc++-v3/include/std/inplace_vector 
b/libstdc++-v3/include/std/inplace_vector
index a2b5f31be92..b16edcb98d9 100644
--- a/libstdc++-v3/include/std/inplace_vector
+++ b/libstdc++-v3/include/std/inplace_vector
@@ -32,6 +32,7 @@
 
 #pragma GCC system_header
 
+#define __glibcxx_want_constexpr_inplace_vector
 #define __glibcxx_want_hardened_inplace_vector
 #define __glibcxx_want_inplace_vector
 #include <bits/version.h>
@@ -853,22 +854,25 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       constexpr void
       _M_init()
       {
-       if !consteval
+#if __glibcxx_start_lifetime
+       std::start_lifetime(_M_elems);
+#else
+       if consteval
          {
-#if __glibcxx_start_lifetime_as
-           std::start_lifetime_as_array<_Tp>(data(), _Nm);
-#endif
-         }
-       else
-         {
-           // TODO: use new(_M_elems) _Tp[_Nm]() once PR121068 is fixed
            if constexpr (is_trivially_default_constructible_v<_Tp>
                            && is_trivially_copyable_v<_Tp>)
              for (size_t __i = 0; __i < _Nm; ++__i)
                _M_elems[__i] = _Tp();
            else
-             __builtin_unreachable(); // only trivial types are supported at 
compile time
+# if __has_builtin(__builtin_constexpr_diag)
+            __builtin_constexpr_diag(2, "",
+               "std::inplace_vector supports only trivally copyable and "
+               "trivially default constructible types at compile time");
+# else
+            __builtin_unreachable();
+# endif
          }
+#endif
       }
 
       static constexpr void
diff --git a/libstdc++-v3/testsuite/23_containers/inplace_vector/cons/1.cc 
b/libstdc++-v3/testsuite/23_containers/inplace_vector/cons/1.cc
index 2982af27785..264fba572ca 100644
--- a/libstdc++-v3/testsuite/23_containers/inplace_vector/cons/1.cc
+++ b/libstdc++-v3/testsuite/23_containers/inplace_vector/cons/1.cc
@@ -108,13 +108,6 @@ test_default()
   VERIFY( z0.empty() );
   VERIFY( z0.begin() == z0.end() );
 
-#ifdef __cpp_lib_constexpr_inplace_vector
-#error remove the consteval check
-#endif
-  if consteval {
-    return;
-  }
-
   std::inplace_vector<X, 5> cx;
   VERIFY( cx.size() == 0 );
   VERIFY( cx.capacity() == 5 );
@@ -192,13 +185,6 @@ test_n()
 #endif
 #endif
 
-#ifdef __cpp_lib_constexpr_inplace_vector
-#error remove the consteval check
-#endif
-  if consteval {
-    return;
-  }
-
   std::inplace_vector<X, 5> cx(3);
   VERIFY( cx.size() == 3 );
   VERIFY( cx.capacity() == 5 );
@@ -269,13 +255,6 @@ test_n_val()
 #endif
 #endif
 
-#ifdef __cpp_lib_constexpr_inplace_vector
-#error remove the consteval check
-#endif
-  if consteval {
-    return;
-  }
-
   std::inplace_vector<X, 5> cx(4);
   VERIFY( cx.size() == 4 );
   VERIFY( cx.capacity() == 5 );
@@ -320,45 +299,38 @@ test_initializer_list()
   VERIFY( z0.empty() );
   VERIFY( z0.begin() == z0.end() );
 
-#ifdef __cpp_exceptions
-#ifndef __cpp_lib_constexpr_exceptions
-  if not consteval {
-#endif
-    try
-    {
-      std::inplace_vector<int, 2> ct{11, 22, 33};
-      VERIFY(false);
-    }
-    catch (std::bad_alloc const&)
-    {
-    }
-
-    try
-    {
-      std::inplace_vector<int, 0> ct{11, 22};
-      VERIFY(false);
-    }
-    catch (std::bad_alloc const&)
-    {
-    }
-#ifndef __cpp_lib_constexpr_exceptions
-  }
-#endif
-#endif
-
-#ifdef __cpp_lib_constexpr_inplace_vector
-#error remove the consteval check
-#endif
-  if consteval {
-    return;
-  }
-
   std::inplace_vector<X, 5> cx{X(), X(), X(), X()};
   VERIFY( cx.size() == 4 );
   VERIFY( cx.capacity() == 5 );
   VERIFY( not cx.empty() );
   VERIFY( cx.begin() + 4 == cx.end() );
   (void) cx[3];
+
+#ifdef __cpp_exceptions
+# ifndef __cpp_lib_constexpr_exceptions
+  if consteval {
+    return;
+  }
+# endif
+
+  try
+  {
+    std::inplace_vector<int, 2> ct{11, 22, 33};
+    VERIFY(false);
+  }
+  catch (std::bad_alloc const&)
+  {
+  }
+
+  try
+  {
+    std::inplace_vector<int, 0> ct{11, 22};
+    VERIFY(false);
+  }
+  catch (std::bad_alloc const&)
+  {
+  }
+#endif
 }
 
 constexpr std::inplace_vector<int, 0> e0;
@@ -375,6 +347,16 @@ constexpr std::inplace_vector<int, 5> g5 = [] {
   return res;
 }();
 
+constexpr std::inplace_vector<X, 5> h1;
+constexpr std::inplace_vector<X, 5> h2(2, X());
+constexpr std::inplace_vector<X, 5> h3 = h2;
+constexpr std::inplace_vector<X, 5> h4{X(), X(), X()};
+constexpr std::inplace_vector<X, 5> h5 = [] {
+  std::inplace_vector<X, 5> res;
+  res = h3;
+  return res;
+}();
+
 int main()
 {
   auto tests = [] {
diff --git a/libstdc++-v3/testsuite/23_containers/inplace_vector/copy.cc 
b/libstdc++-v3/testsuite/23_containers/inplace_vector/copy.cc
index 11260c63313..a2f5e7d3486 100644
--- a/libstdc++-v3/testsuite/23_containers/inplace_vector/copy.cc
+++ b/libstdc++-v3/testsuite/23_containers/inplace_vector/copy.cc
@@ -160,13 +160,6 @@ test_ctor()
   auto c5 = materialize<5, int>({1, 2, 3, 4, 5});
   VERIFY( eq(c5, {1, 2, 3, 4, 5}) );
 
-#ifdef __cpp_lib_constexpr_inplace_vector
-#error remove the consteval check
-#endif
-  if consteval {
-    return;
-  }
-
   auto x0 = materialize<3, X>({});
   VERIFY( x0.empty() );
 
@@ -206,13 +199,6 @@ test_assign()
   c = materialize<5, int>({});
   VERIFY( c.empty() );
 
-#ifdef __cpp_lib_constexpr_inplace_vector
-#error remove the consteval check
-#endif
-  if consteval {
-    return;
-  }
-
   std::inplace_vector<X, 5> x;
   x = materialize<5, X>({});
   VERIFY( x.empty() );
@@ -238,6 +224,10 @@ constexpr auto t1 = materialize<3, int>({});
 constexpr auto t2 = materialize<3, int>({1, 2});
 constexpr auto t3 = materialize<3, int>({11, 22, 33});
 
+constexpr auto u1 = materialize<3, X>({});
+constexpr auto u2 = materialize<3, X>({1, 2});
+constexpr auto u3 = materialize<3, X>({11, 22, 33});
+
 int main()
 {
   auto tests = [] {
diff --git 
a/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/assign.cc 
b/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/assign.cc
index 577c1047708..27c2f09db84 100644
--- a/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/assign.cc
+++ b/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/assign.cc
@@ -407,15 +407,10 @@ int main()
     test_assign_empty<0, int>();
     test_assign_empty<0, X>();
     test_assign_empty<2, int>();
+    test_assign_empty<2, X>();
 
     test_assigns<int>();
-#ifdef __cpp_lib_constexpr_inplace_vector
-#error uncomemnt test_inserts<X>()
-#endif
-    if !consteval {
-      test_assign_empty<2, X>();
-      test_assigns<X>();
-    }
+    test_assigns<X>();
 
     test_iota<long long>();
 #ifdef __SIZEOF_INT128__
diff --git 
a/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/erase.cc 
b/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/erase.cc
index 8b82ab4189c..36096da4feb 100644
--- a/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/erase.cc
+++ b/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/erase.cc
@@ -101,14 +101,9 @@ int main()
     test_erase_all_or_none<0, X>();
 
     test_erase_all_or_none<4, int>();
+    test_erase_all_or_none<4, X>();
 
     test_erase<int>();
-#ifdef __cpp_lib_constexpr_inplace_vector
-#error uncomemnt test_inserts<X>()
-#endif
-    if ! consteval {
-      test_erase_all_or_none<4, X>();
-    }
     return true;
   };
 
diff --git 
a/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/multi_insert.cc 
b/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/multi_insert.cc
index bde66847a34..4b36b5151ed 100644
--- 
a/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/multi_insert.cc
+++ 
b/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/multi_insert.cc
@@ -562,11 +562,11 @@ test_iota()
   VERIFY( eq<T>(v, {a, 15}) );
 
 #ifdef __cpp_exceptions
-#ifndef __cpp_lib_constexpr_exceptions
+# ifndef __cpp_lib_constexpr_exceptions
   if consteval {
     return;
   }
-#endif
+# endif
   constexpr T max = std::numeric_limits<T>::max();
   try
   {
@@ -615,7 +615,6 @@ test_iota()
   {
   }
   VERIFY( prefix<T>(vc, {a, 15}) );
-
 #endif
 }
 
@@ -625,15 +624,10 @@ int main()
     test_add_to_full<0, int>();
     test_add_to_full<0, X>();
     test_add_to_full<4, int>();
+    test_add_to_full<4, X>();
 
     test_inserts<int>();
-#ifdef __cpp_lib_constexpr_inplace_vector
-#error uncomemnt test_inserts<X>()
-#endif
-    if !consteval {
-      test_add_to_full<4, X>();
-      test_inserts<X>();
-    }
+    test_inserts<X>();
 
     test_iota<long long>();
 #ifdef __SIZEOF_INT128__
diff --git 
a/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/single_insert.cc
 
b/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/single_insert.cc
index 2b5e76a6f63..ffe5ed3374d 100644
--- 
a/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/single_insert.cc
+++ 
b/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/single_insert.cc
@@ -216,17 +216,12 @@ int main()
     test_add_to_full<0, Y>();
 
     test_add_to_full<4, int>();
+    test_add_to_full<4, X>();
     test_add_to_full<4, Y>();
 
     test_inserts<int>();
     test_inserts<Y>();
-#ifdef __cpp_lib_constexpr_inplace_vector
-#error enable tests bellow
-#endif
-    if ! consteval {
-      test_add_to_full<4, X>();
-      test_inserts<X>();
-    }
+    test_inserts<X>();
     return true;
   };
 
diff --git a/libstdc++-v3/testsuite/23_containers/inplace_vector/move.cc 
b/libstdc++-v3/testsuite/23_containers/inplace_vector/move.cc
index 8b5c3e9f247..5419dc0edb6 100644
--- a/libstdc++-v3/testsuite/23_containers/inplace_vector/move.cc
+++ b/libstdc++-v3/testsuite/23_containers/inplace_vector/move.cc
@@ -67,7 +67,7 @@ struct Z
 template<size_t N, typename T>
   constexpr std::inplace_vector<T, N>
   materialize(std::initializer_list<int> il)
-  { 
+  {
     std::inplace_vector<T, N> res;
     for (int x : il)
       res.emplace_back(x);
@@ -199,13 +199,6 @@ test_ctor()
   auto c5 = materialize<5, int>({1, 2, 3, 4, 5});
   VERIFY( eq(c5, {1, 2, 3, 4, 5}) );
 
-#ifdef __cpp_lib_constexpr_inplace_vector
-#error remove the consteval check
-#endif
-  if consteval {
-    return;
-  }
-
   auto x0 = materialize<3, X>({});
   VERIFY( x0.empty() );
 
@@ -235,7 +228,7 @@ test_assign()
 
   c = materialize<5, int>({1, 2, 3});
   VERIFY( eq(c, {1, 2, 3}) );
- 
+
   c = materialize<5, int>({1, 2, 3, 4, 5});
   VERIFY( eq(c, {1, 2, 3, 4, 5}) );
 
@@ -245,20 +238,13 @@ test_assign()
   c = materialize<5, int>({});
   VERIFY( c.empty() );
 
-#ifdef __cpp_lib_constexpr_inplace_vector
-#error remove the consteval check
-#endif
-  if consteval {
-    return;
-  }
-
   std::inplace_vector<X, 5> x;
   x = materialize<5, X>({});
   VERIFY( x.empty() );
 
   x = materialize<5, X>({1, 2, 3});
   VERIFY( eq(x, {1, 2, 3}) );
- 
+
   x = materialize<5, X>({1, 2, 3, 4, 5});
   VERIFY( eq(x, {1, 2, 3, 4, 5}) );
 
@@ -279,7 +265,7 @@ test_swap()
   e0a.swap(e0b);
   VERIFY( e0a.empty() );
   VERIFY( e0b.empty() );
- 
+
   std::inplace_vector<X, 0> e1a, e1b;
   swap(e1a, e1b);
   VERIFY( e1a.empty() );
@@ -314,13 +300,6 @@ test_swap()
   VERIFY( eq(c3, {1, 2, 3}) );
   VERIFY( eq(c5, {1, 2, 3, 4, 5}) );
 
-#ifdef __cpp_lib_constexpr_inplace_vector
-#error remove the consteval check
-#endif
-  if consteval {
-    return;
-  }
-
   std::inplace_vector<X, 5> x0;
   std::inplace_vector<X, 5> x3 = {1, 2, 3};
   std::inplace_vector<X, 5> x5 = {1, 2, 3, 4, 5};
@@ -348,6 +327,10 @@ constexpr auto t1 = materialize<3, int>({});
 constexpr auto t2 = materialize<3, int>({1, 2});
 constexpr auto t3 = materialize<3, int>({11, 22, 33});
 
+constexpr auto u1 = materialize<3, X>({});
+constexpr auto u2 = materialize<3, X>({1, 2});
+constexpr auto u3 = materialize<3, X>({11, 22, 33});
+
 int main()
 {
   auto tests = [] {
diff --git a/libstdc++-v3/testsuite/23_containers/inplace_vector/version.cc 
b/libstdc++-v3/testsuite/23_containers/inplace_vector/version.cc
index 493e86dc6dd..73be2eeff4f 100644
--- a/libstdc++-v3/testsuite/23_containers/inplace_vector/version.cc
+++ b/libstdc++-v3/testsuite/23_containers/inplace_vector/version.cc
@@ -9,6 +9,12 @@
 # error "Feature-test macro for inplace_vector has wrong value in 
<inplace_vector>"
 #endif
 
+#ifndef __cpp_lib_constexpr_inplace_vector
+# error "Feature-test macro for constexpr_inplace_vector missing in 
<constexpr_inplace_vector>"
+#elif __cpp_lib_constexpr_inplace_vector != 202502LL
+# error "Feature-test macro for constexpr_inplace_vector has wrong value in 
<constexpr_inplace_vector>"
+#endif
+
 #undef __cpp_lib_inplace_vector
 
 #include <version>
@@ -18,3 +24,9 @@
 #elif __cpp_lib_inplace_vector != 202603L
 # error "Feature-test macro for inplace_vector has wrong value in <version>"
 #endif
+
+#ifndef __cpp_lib_constexpr_inplace_vector
+# error "Feature-test macro for constexpr_inplace_vector missing in 
<constexpr_inplace_vector>"
+#elif __cpp_lib_constexpr_inplace_vector != 202502LL
+# error "Feature-test macro for constexpr_inplace_vector has wrong value in 
<constexpr_inplace_vector>"
+#endif
-- 
2.55.0

Reply via email to