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