aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3/testsuite
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2021-11-11 14:05:35 +0000
committerJonathan Wakely <jwakely@redhat.com>2021-11-12 00:42:39 +0000
commit1ae8edf5f73ca5c3bf132cc52825dc1f709499dd (patch)
tree8bc8ecc241cb38121c561086139b9f08c44e022c /libstdc++-v3/testsuite
parentb39265d4fe13e3e8ce5021642e5092e74effb643 (diff)
downloadgcc-1ae8edf5f73ca5c3bf132cc52825dc1f709499dd.zip
gcc-1ae8edf5f73ca5c3bf132cc52825dc1f709499dd.tar.gz
gcc-1ae8edf5f73ca5c3bf132cc52825dc1f709499dd.tar.bz2
libstdc++: Implement constexpr std::vector for C++20
This implements P1004R2 ("Making std::vector constexpr") for C++20. For now, debug mode vectors are not supported in constant expressions. To make that work we might need to disable all attaching/detaching of safe iterators. That can be fixed later. Co-authored-by: Josh Marshall <joshua.r.marshall.1991@gmail.com> libstdc++-v3/ChangeLog: * include/bits/alloc_traits.h (_Destroy): Make constexpr for C++20 mode. * include/bits/allocator.h (__shrink_to_fit::_S_do_it): Likewise. * include/bits/stl_algobase.h (__fill_a1): Declare _Bit_iterator overload constexpr for C++20. * include/bits/stl_bvector.h (_Bit_type, _S_word_bit): Move out of inline namespace. (_Bit_reference, _Bit_iterator_base, _Bit_iterator) (_Bit_const_iterator, _Bvector_impl_data, _Bvector_base) (vector<bool, A>>): Add constexpr to every member function. (_Bvector_base::_M_allocate): Initialize storage during constant evaluation. (vector<bool, A>::_M_initialize_value): Use __fill_bvector_n instead of memset. (__fill_bvector_n): New helper function to replace memset during constant evaluation. * include/bits/stl_uninitialized.h (__uninitialized_copy<false>): Move logic to ... (__do_uninit_copy): New function. (__uninitialized_fill<false>): Move logic to ... (__do_uninit_fill): New function. (__uninitialized_fill_n<false>): Move logic to ... (__do_uninit_fill_n): New function. (__uninitialized_copy_a): Add constexpr. Use __do_uninit_copy. (__uninitialized_move_a, __uninitialized_move_if_noexcept_a): Add constexpr. (__uninitialized_fill_a): Add constexpr. Use __do_uninit_fill. (__uninitialized_fill_n_a): Add constexpr. Use __do_uninit_fill_n. (__uninitialized_default_n, __uninitialized_default_n_a) (__relocate_a_1, __relocate_a): Add constexpr. * include/bits/stl_vector.h (_Vector_impl_data, _Vector_impl) (_Vector_base, vector): Add constexpr to every member function. (_Vector_impl::_S_adjust): Disable ASan annotation during constant evaluation. (_Vector_base::_S_use_relocate): Disable bitwise-relocation during constant evaluation. (vector::_Temporary_value): Use a union for storage. * include/bits/vector.tcc (vector, vector<bool>): Add constexpr to every member function. * include/std/vector (erase_if, erase): Add constexpr. * testsuite/23_containers/headers/vector/synopsis.cc: Add constexpr for C++20 mode. * testsuite/23_containers/vector/bool/cmp_c++20.cc: Change to compile-only test using constant expressions. * testsuite/23_containers/vector/bool/capacity/29134.cc: Adjust namespace for _S_word_bit. * testsuite/23_containers/vector/bool/modifiers/insert/31370.cc: Likewise. * testsuite/23_containers/vector/cmp_c++20.cc: Likewise. * testsuite/23_containers/vector/cons/89164.cc: Adjust errors for C++20 and move C++17 test to ... * testsuite/23_containers/vector/cons/89164_c++17.cc: ... here. * testsuite/23_containers/vector/bool/capacity/constexpr.cc: New test. * testsuite/23_containers/vector/bool/cons/constexpr.cc: New test. * testsuite/23_containers/vector/bool/element_access/constexpr.cc: New test. * testsuite/23_containers/vector/bool/modifiers/assign/constexpr.cc: New test. * testsuite/23_containers/vector/bool/modifiers/constexpr.cc: New test. * testsuite/23_containers/vector/bool/modifiers/swap/constexpr.cc: New test. * testsuite/23_containers/vector/capacity/constexpr.cc: New test. * testsuite/23_containers/vector/cons/constexpr.cc: New test. * testsuite/23_containers/vector/data_access/constexpr.cc: New test. * testsuite/23_containers/vector/element_access/constexpr.cc: New test. * testsuite/23_containers/vector/modifiers/assign/constexpr.cc: New test. * testsuite/23_containers/vector/modifiers/constexpr.cc: New test. * testsuite/23_containers/vector/modifiers/swap/constexpr.cc: New test.
Diffstat (limited to 'libstdc++-v3/testsuite')
-rw-r--r--libstdc++-v3/testsuite/23_containers/headers/vector/synopsis.cc14
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/bool/capacity/29134.cc5
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/bool/capacity/constexpr.cc115
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/bool/cmp_c++20.cc19
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/bool/cons/constexpr.cc280
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/bool/element_access/constexpr.cc102
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/assign/constexpr.cc216
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/constexpr.cc248
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/insert/31370.cc6
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/swap/constexpr.cc66
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/capacity/constexpr.cc101
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/cmp_c++20.cc49
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/cons/89164.cc16
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/cons/89164_c++17.cc39
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/cons/constexpr.cc279
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/data_access/constexpr.cc26
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/element_access/constexpr.cc91
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/modifiers/assign/constexpr.cc207
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/modifiers/constexpr.cc226
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/modifiers/swap/constexpr.cc51
20 files changed, 2107 insertions, 49 deletions
diff --git a/libstdc++-v3/testsuite/23_containers/headers/vector/synopsis.cc b/libstdc++-v3/testsuite/23_containers/headers/vector/synopsis.cc
index 0fc46fe..f02659f 100644
--- a/libstdc++-v3/testsuite/23_containers/headers/vector/synopsis.cc
+++ b/libstdc++-v3/testsuite/23_containers/headers/vector/synopsis.cc
@@ -27,13 +27,21 @@
# define NOTHROW(X)
#endif
+#if __cplusplus >= 202002L
+# define CONSTEXPR constexpr
+#else
+# define CONSTEXPR
+#endif
+
namespace std {
template <class T, class Allocator> class vector;
template <class T, class Allocator>
+ CONSTEXPR
bool operator==(const vector<T,Allocator>& x,
const vector<T,Allocator>& y);
+#if __cplusplus < 202002L
template <class T, class Allocator>
bool operator< (const vector<T,Allocator>& x,
const vector<T,Allocator>& y);
@@ -53,17 +61,21 @@ namespace std {
template <class T, class Allocator>
bool operator<=(const vector<T,Allocator>& x,
const vector<T,Allocator>& y);
+#endif
template <class T, class Allocator>
+ CONSTEXPR
void swap(vector<T,Allocator>& x, vector<T,Allocator>& y)
NOTHROW(noexcept(x.swap(y)));
template <class Allocator> class vector<bool,Allocator>;
template <class Allocator>
+ CONSTEXPR
bool operator==(const vector<bool,Allocator>& x,
const vector<bool,Allocator>& y);
+#if __cplusplus < 202002L
template <class Allocator>
bool operator< (const vector<bool,Allocator>& x,
const vector<bool,Allocator>& y);
@@ -83,7 +95,9 @@ namespace std {
template <class Allocator>
bool operator<=(const vector<bool,Allocator>& x,
const vector<bool,Allocator>& y);
+#endif
template <class Allocator>
+ CONSTEXPR
void swap(vector<bool,Allocator>& x, vector<bool,Allocator>& y);
}
diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/capacity/29134.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/capacity/29134.cc
index 43f3343..da5e6b4 100644
--- a/libstdc++-v3/testsuite/23_containers/vector/bool/capacity/29134.cc
+++ b/libstdc++-v3/testsuite/23_containers/vector/bool/capacity/29134.cc
@@ -26,12 +26,7 @@ void test01()
{
using std::vector;
using std::numeric_limits;
-
-#ifdef _GLIBCXX_DEBUG
- using std::_GLIBCXX_STD_C::_S_word_bit;
-#else
using std::_S_word_bit;
-#endif
// Actually, vector<bool> is special, see libstdc++/31370.
vector<bool> vb;
diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/capacity/constexpr.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/capacity/constexpr.cc
new file mode 100644
index 0000000..52b10b6
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/vector/bool/capacity/constexpr.cc
@@ -0,0 +1,115 @@
+// { dg-options "-std=gnu++20" }
+// { dg-do compile { target c++20 } }
+// { dg-xfail-if "not supported" { debug-mode } }
+
+#include <vector>
+#include <testsuite_hooks.h>
+
+constexpr std::size_t
+capacity_for(std::size_t n)
+{
+ std::size_t N = std::vector<bool>(1).capacity();
+ if (auto r = n % N)
+ return n - r + N;
+ return n;
+}
+
+constexpr bool
+test_empty()
+{
+ std::vector<bool> v;
+ VERIFY( v.empty() );
+ v = {1};
+ VERIFY( !v.empty() );
+
+ return true;
+}
+
+static_assert( test_empty() );
+
+constexpr bool
+test_size()
+{
+ std::vector<bool> v;
+ VERIFY( v.size() == 0 );
+ v = {1};
+ VERIFY( v.size() == 1 );
+
+ VERIFY( v.max_size() != 0 );
+
+ return true;
+}
+
+static_assert( test_size() );
+
+constexpr bool
+test_capacity()
+{
+ std::vector<bool> v;
+ VERIFY( v.size() == 0 );
+ VERIFY( v.capacity() == v.size() );
+ v = {false, false, false};
+ VERIFY( v.size() == 3 );
+ VERIFY( v.capacity() >= v.size() );
+
+ return true;
+}
+
+static_assert( test_capacity() );
+
+constexpr bool
+test_resize()
+{
+ std::vector<bool> v;
+ v.reserve(9);
+ VERIFY( v.size() == 0 );
+ VERIFY( v.capacity() == capacity_for(9) );
+ v.resize(5);
+ VERIFY( v.size() == 5 );
+ VERIFY( v.capacity() == capacity_for(9) );
+ v.resize(900, true);
+ VERIFY( v.size() == 900 );
+ VERIFY( v.capacity() == capacity_for(900) );
+ VERIFY( v[10] == true );
+
+ return true;
+}
+
+static_assert( test_resize() );
+
+constexpr bool
+test_reserve()
+{
+ std::vector<bool> v;
+ v.reserve(9);
+ VERIFY( v.size() == 0 );
+ VERIFY( v.capacity() == capacity_for(9) );
+ v.resize(2);
+ VERIFY( v.size() == 2 );
+ VERIFY( v.capacity() == capacity_for(9) );
+ v.resize(300);
+ v.resize(100);
+ VERIFY( v.size() == 100 );
+ VERIFY( v.capacity() == capacity_for(300) );
+
+ return true;
+}
+
+static_assert( test_reserve() );
+
+constexpr bool
+test_shrink_to_fit()
+{
+ std::vector<bool> v;
+ v.reserve(9);
+ v.shrink_to_fit();
+ VERIFY( v.capacity() == 0 );
+ v.reserve(9);
+ v.resize(5);
+ v.shrink_to_fit();
+ VERIFY( v.capacity() == capacity_for(v.size()) );
+
+ return true;
+}
+
+static_assert( test_shrink_to_fit() );
diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/cmp_c++20.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/cmp_c++20.cc
index 7a730df..ae2bd03 100644
--- a/libstdc++-v3/testsuite/23_containers/vector/bool/cmp_c++20.cc
+++ b/libstdc++-v3/testsuite/23_containers/vector/bool/cmp_c++20.cc
@@ -16,12 +16,13 @@
// <http://www.gnu.org/licenses/>.
// { dg-options "-std=gnu++2a" }
-// { dg-do run { target c++2a } }
+// { dg-do compile { target c++2a } }
+// { dg-xfail-if "not supported" { debug-mode } }
#include <vector>
#include <testsuite_hooks.h>
-void
+constexpr bool
test01()
{
std::vector<bool> c1{ 1, 0, 1 }, c2{ 1, 0, 1, 0 }, c3{ 1, 1, 1 };
@@ -38,9 +39,11 @@ test01()
static_assert( std::three_way_comparable<std::vector<bool>,
std::strong_ordering> );
+
+ return true;
}
-void
+constexpr bool
test05()
{
// vector<bool> iterators are random access, so should support <=>
@@ -63,11 +66,9 @@ test05()
static_assert( std::same_as<decltype(c.begin() <=> c.begin()),
std::strong_ordering> );
-}
-int
-main()
-{
- test01();
- test05();
+ return true;
}
+
+static_assert( test01() );
+static_assert( test05() );
diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/cons/constexpr.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/cons/constexpr.cc
new file mode 100644
index 0000000..edd5060
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/vector/bool/cons/constexpr.cc
@@ -0,0 +1,280 @@
+// { dg-options "-std=gnu++20" }
+// { dg-do compile { target c++20 } }
+// { dg-xfail-if "not supported" { debug-mode } }
+
+#include <vector>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+template<typename T>
+struct Alloc : std::allocator<T>
+{
+ using std::allocator<T>::allocator;
+
+ constexpr explicit Alloc(int p) : personality(p) { }
+
+ template<typename U>
+ constexpr Alloc(const Alloc<U>& a) : personality(a.personality) { }
+
+ int personality = 0;
+
+ constexpr Alloc select_on_container_copy_construction() const
+ { return Alloc(-1); }
+
+ constexpr bool operator==(const Alloc& a) const noexcept
+ { return personality == a.personality; }
+};
+
+namespace default_constructor_global_scope
+{
+ constexpr std::vector<bool> v1;
+ static_assert(v1.size() == 0);
+ static_assert(v1.capacity() == 0);
+
+ constexpr std::allocator<bool> a;
+ constexpr std::vector<bool> v2(a);
+ static_assert(v2.size() == 0);
+ static_assert(v2.capacity() == 0);
+
+ constexpr Alloc<bool> aa(10);
+ constexpr std::vector<bool, Alloc<bool>> v3(aa);
+ static_assert(v3.size() == 0);
+ static_assert(v3.capacity() == 0);
+ static_assert(v3.get_allocator() == aa);
+}
+
+constexpr bool
+default_constructor_function_scope()
+{
+ // vector()
+
+ std::vector<bool> v1;
+ VERIFY(v1.size() == 0);
+ VERIFY(v1.capacity() == 0);
+
+ // vector(const Allocator&)
+
+ const std::allocator<bool> a;
+ std::vector<bool> v2(a);
+ VERIFY(v2.size() == 0);
+ VERIFY(v2.capacity() == 0);
+
+ const Alloc<bool> aa(10);
+ std::vector<bool, Alloc<bool>> v3(aa);
+ VERIFY(v3.size() == 0);
+ VERIFY(v3.capacity() == 0);
+ VERIFY(v3.get_allocator() == aa);
+
+ return true;
+}
+
+static_assert( default_constructor_function_scope() );
+
+constexpr bool
+sequence_constructors()
+{
+ // vector(size_type, const Allocator& = Allocator())
+
+ std::vector<bool> v0(0);
+ VERIFY(v0.size() == 0);
+
+ std::vector<bool> v1(1);
+ VERIFY(v1.size() == 1);
+
+ std::vector<bool> v2(2);
+ VERIFY(v2.size() == 2);
+
+ std::vector<bool> v50(50);
+ VERIFY(v50.size() == 50);
+
+ const std::allocator<bool> a;
+ std::vector<bool> a0(0, a);
+ VERIFY(a0.size() == 0);
+
+ std::vector<bool> a1(1, a);
+ VERIFY(a1.size() == 1);
+
+ std::vector<bool> a2(2, a);
+ VERIFY(a2.size() == 2);
+
+ std::vector<bool> a50(50, a);
+ VERIFY(a50.size() == 50);
+
+ const Alloc<bool> la(10);
+ std::vector<bool, Alloc<bool>> l0(0, la);
+ VERIFY(l0.size() == 0);
+ VERIFY(l0.get_allocator() == la);
+
+ std::vector<bool, Alloc<bool>> l1(1, la);
+ VERIFY(l1.size() == 1);
+ VERIFY(l1.get_allocator() == la);
+
+ std::vector<bool, Alloc<bool>> l2(2, la);
+ VERIFY(l2.size() == 2);
+ VERIFY(l2.get_allocator() == la);
+
+ std::vector<bool, Alloc<bool>> l50(50, la);
+ VERIFY(l50.size() == 50);
+ VERIFY(l50.get_allocator() == la);
+
+ // vector(size_type, const T&, const Allocator& = Allocator())
+
+ std::vector<bool> v3(3, true);
+ VERIFY(v3.size() == 3);
+ VERIFY(v3[0] == true && v3[2] == true);
+
+ std::vector<bool> a3(3, false, a);
+ VERIFY(a3.size() == 3);
+ VERIFY(a3[0] == false && a3[2] == false);
+
+ std::vector<bool, Alloc<bool>> l3(3, true, la);
+ VERIFY(l3.size() == 3);
+ VERIFY(l3[0] == true && l3[2] == true);
+ VERIFY(l3.get_allocator() == la);
+
+ return true;
+}
+
+static_assert(sequence_constructors());
+
+constexpr bool
+iterator_range_constructor()
+{
+ // vector(InputIterator, InputIterator, const Allocator& = Allocator())
+
+ short range[3] = { true, false, true };
+
+ std::vector<bool> v0(std::begin(range), std::end(range));
+ VERIFY(v0.size() == std::size(range));
+ VERIFY(v0[0] == true && v0[1] == false && v0[2] == true);
+
+ const Alloc<bool> a(5);
+ std::vector<bool, Alloc<bool>> l0(std::begin(range), std::end(range), a);
+ VERIFY(l0.size() == std::size(range));
+ VERIFY(l0.get_allocator() == a);
+ VERIFY(l0[0] == true && l0[1] == false && l0[2] == true);
+
+ struct input_iterator
+ {
+ using iterator_category = std::input_iterator_tag;
+ using value_type = bool;
+ using pointer = const bool*;
+ using reference = bool;
+ using difference_type = int;
+
+ constexpr input_iterator() : val(0) { }
+ constexpr input_iterator(int i) : val(i) { }
+
+ constexpr input_iterator& operator++() { --val; return *this; }
+ constexpr input_iterator operator++(int) { return {val--}; }
+
+ constexpr bool operator*() const { return val % 2; }
+ constexpr const bool* operator->() const { return nullptr; }
+
+ constexpr bool operator==(const input_iterator&) const = default;
+
+ int val;
+ };
+
+ std::vector<bool> v1(input_iterator(3), input_iterator());
+ VERIFY(v1.size() == 3);
+ VERIFY(v1[0] == true && v1[1] == false && v1[2] == true);
+
+ std::vector<bool, Alloc<bool>> l1(input_iterator(2), input_iterator(), a);
+ VERIFY(l1.size() == 2);
+ VERIFY(l1.get_allocator() == a);
+ VERIFY(l1[0] == false && l1[1] == true);
+
+ return true;
+}
+
+static_assert(iterator_range_constructor());
+
+constexpr bool
+initializer_list_constructor()
+{
+ // vector(initializer_list<T>, const Allocator& = Allocator())
+
+ std::vector<bool> v0({ false, true, false });
+ VERIFY(v0.size() == 3);
+ VERIFY(v0[0] == false && v0[1] == true && v0[2] == false);
+
+ const Alloc<bool> a(5);
+ std::vector<bool, Alloc<bool>> l0({ true, false, false }, a);
+ VERIFY(l0.size() == 3);
+ VERIFY(l0.get_allocator() == a);
+ VERIFY(l0[0] == true && l0[1] == false && l0[2] == false);
+
+ return true;
+}
+
+static_assert(initializer_list_constructor());
+
+constexpr bool
+copy_constructor()
+{
+ const std::vector<bool> v0({ 1, 0, 0, 1, 0, 1, 1, 0 });
+ const std::vector<bool, Alloc<bool>> l0({ 0, 0, 1, 1, 0, 1, 0, 1, 1, 1 });
+
+ // vector(const vector&)
+
+ std::vector<bool> v1(v0);
+ VERIFY( v1.size() == v0.size() );
+ VERIFY( v1[0] == v0[0] && v1[1] == v0[1] && v1[2] == v0[2] );
+ VERIFY( v1.get_allocator() == v0.get_allocator() );
+
+ const Alloc<bool> as(6);
+ std::vector<bool, Alloc<bool>> s1(3, true, as);
+ std::vector<bool, Alloc<bool>> s2(s1);
+ VERIFY( s2.size() == s1.size() );
+ VERIFY( s2.get_allocator().personality == -1 );
+
+ // vector(const vector&, const Allocator&)
+
+ const Alloc<bool> a(6);
+ std::vector<bool, Alloc<bool>> l1(l0, a);
+ VERIFY( l1.size() == l0.size() );
+ VERIFY( l1[0] == l0[0] && l1[1] == l0[1] && l1[2] == l0[2] );
+ VERIFY( l1.get_allocator() == a );
+ VERIFY( l1.get_allocator() != l0.get_allocator() );
+
+ return true;
+}
+
+static_assert(copy_constructor());
+
+constexpr bool
+move_constructor()
+{
+ const std::vector<bool> v0({ 1, 0, 0, 1, 0, 1, 1, 0 });
+ const std::vector<bool, Alloc<bool>> l0({ 0, 0, 1, 1, 0, 1, 0, 1, 1, 1 });
+
+ // vector(const vector&)
+
+ std::vector<bool> v1(v0);
+ std::vector<bool> v2(std::move(v1));
+ VERIFY( v2.size() == v0.size() );
+ VERIFY( v1.empty() );
+ VERIFY( v2[0] == v0[0] && v2[1] == v0[1] && v2[2] == v0[2] );
+ VERIFY( v2.get_allocator() == v0.get_allocator() );
+
+ // vector(const vector&, const Allocator&)
+
+ const Alloc<bool> a(6);
+ std::vector<bool, Alloc<bool>> l1(l0);
+ std::vector<bool, Alloc<bool>> l2(std::move(l1), a);
+ VERIFY( l2.size() == l0.size() );
+ VERIFY( l2[0] == l0[0] && l2[1] == l0[1] && l2[2] == l0[2] );
+ VERIFY( l2.get_allocator() == a );
+ VERIFY( l2.get_allocator() != l0.get_allocator() );
+
+ std::vector<bool, Alloc<bool>> l3(std::move(l2), a);
+ VERIFY( l3.size() == l0.size() );
+ VERIFY( l3[0] == l0[0] && l3[1] == l0[1] && l3[2] == l0[2] );
+ VERIFY( l3.get_allocator() == a );
+ VERIFY( l3.get_allocator() == l2.get_allocator() );
+
+ return true;
+}
+
+static_assert(move_constructor());
diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/element_access/constexpr.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/element_access/constexpr.cc
new file mode 100644
index 0000000..6fa8758
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/vector/bool/element_access/constexpr.cc
@@ -0,0 +1,102 @@
+// { dg-options "-std=gnu++20" }
+// { dg-do compile { target c++20 } }
+// { dg-xfail-if "not supported" { debug-mode } }
+
+#include <vector>
+#include <testsuite_hooks.h>
+
+constexpr bool
+test_iterators()
+{
+ std::vector<bool> v;
+ VERIFY( v.begin() == v.end() );
+ v.reserve(1);
+ VERIFY( v.begin() == v.end() );
+ v.resize(2);
+ VERIFY( v.begin() != v.end() );
+ VERIFY( v.cbegin() == v.begin() );
+ VERIFY( v.crbegin() == v.rbegin() );
+ VERIFY( v.cend() == v.end() );
+ VERIFY( v.crend() == v.rend() );
+
+ auto it = v.begin();
+ VERIFY( *it == v.front() );
+ VERIFY( it++ == v.begin() );
+ VERIFY( ++it == v.end() );
+ VERIFY( (it - 2) == v.begin() );
+ it -= 2;
+ it += 1;
+ VERIFY( (it + 1) == v.end() );
+
+ auto rit = v.rbegin();
+ VERIFY( *rit == v.back() );
+ VERIFY( rit++ == v.rbegin() );
+ VERIFY( ++rit == v.rend() );
+ VERIFY( (rit - 2) == v.rbegin() );
+ rit -= 2;
+ rit += 1;
+ VERIFY( (rit + 1) == v.rend() );
+
+ return true;
+}
+
+static_assert(test_iterators());
+
+constexpr bool
+test_access()
+{
+ std::vector<bool> v{1, 1, 0, 0, 1, 0, 1, 0, 1};
+ std::vector<bool>::reference r1 = v.at(1);
+ VERIFY( r1 );
+ std::vector<bool>::reference r2 = v[2];
+ VERIFY( ! r2 );
+ r1 = r2;
+ VERIFY( ! r1 );
+ VERIFY( ! v[1] );
+ r2 = true;
+ VERIFY( r2 );
+ VERIFY( v[2] );
+
+ const auto& vc = v;
+ VERIFY( vc.at(1) == false );
+ VERIFY( vc.at(1) == v.at(1) );
+ VERIFY( vc.at(1) == vc[1] );
+ VERIFY( vc.front() == vc[0] );
+ VERIFY( vc.back() == vc[2] );
+
+ return true;
+}
+
+static_assert(test_access());
+
+template<typename T = bool>
+ constexpr std::false_type
+ access_empty() { return {}; }
+
+template<typename T = bool>
+ requires (std::bool_constant<(std::vector<T>().at(0), true)>::value)
+ constexpr std::true_type
+ access_empty() { return {}; }
+
+template<typename T = bool>
+ requires (std::bool_constant<(std::vector<T>().back(), true)>::value)
+ constexpr std::true_type
+ access_empty() { return {}; }
+
+static_assert( ! access_empty() );
+
+template<typename T = bool>
+ constexpr std::false_type
+ access_empty_front() { return {}; }
+
+template<typename T = bool>
+ requires (std::bool_constant<(std::vector<T>()[0], true)>::value)
+ constexpr std::true_type
+ access_empty_front() { return {}; }
+
+template<typename T = bool>
+ requires (std::bool_constant<(std::vector<T>().front(), true)>::value)
+ constexpr std::true_type
+ access_empty_front() { return {}; }
+
+static_assert( ! access_empty_front() ); // { dg-error "ambiguous" "PR 103191" { target { ! debug-mode } } }
diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/assign/constexpr.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/assign/constexpr.cc
new file mode 100644
index 0000000..02faa02
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/assign/constexpr.cc
@@ -0,0 +1,216 @@
+// { dg-options "-std=gnu++20" }
+// { dg-do compile { target c++20 } }
+// { dg-xfail-if "not supported" { debug-mode } }
+
+#include <vector>
+#include <testsuite_hooks.h>
+
+template<typename T>
+struct Alloc : std::allocator<T>
+{
+ using std::allocator<T>::allocator;
+
+ constexpr explicit Alloc(int p) : personality(p) { }
+
+ template<typename U>
+ constexpr Alloc(const Alloc<U>& a) : personality(a.personality) { }
+
+ int personality = 0;
+
+ using propagate_on_container_move_assignment = std::false_type;
+
+ constexpr bool operator==(const Alloc& a) const noexcept
+ { return personality == a.personality; }
+};
+
+constexpr std::size_t
+capacity_for(std::size_t n)
+{
+ std::size_t N = std::vector<bool>(1).capacity();
+ if (auto r = n % N)
+ return n - r + N;
+ return n;
+}
+
+constexpr bool
+copy_assign()
+{
+ // vector::operator=(const vector&)
+
+ std::vector<bool> v1, v2;
+ v1 = v1;
+ v2 = v1;
+ VERIFY(v2.size() == 0);
+ VERIFY(v2.capacity() == 0);
+
+ for (int i = 0; i < 10; ++i)
+ v1.push_back(i);
+ v2 = v1;
+ VERIFY(v2.size() == 10);
+ v2.reserve(50);
+ v1.push_back(1);
+ v2 = v1;
+ VERIFY(v2.size() == 11);
+ VERIFY(v2.capacity() == capacity_for(50));
+
+ std::vector<bool, Alloc<bool>> va1(Alloc<bool>(1)), va2(Alloc<bool>(2));
+ va2 = va1;
+ VERIFY( va2.get_allocator().personality == 2 );
+ va1.push_back(999);
+ va2 = va1;
+ VERIFY( va2.get_allocator().personality == 2 );
+
+ return true;
+}
+
+static_assert( copy_assign() );
+
+constexpr bool
+move_assign()
+{
+ // vector::operator=(const vector&)
+
+ std::vector<bool> v1, v2;
+ v1 = std::move(v1);
+ v2 = std::move(v1);
+ VERIFY(v2.size() == 0);
+ VERIFY(v2.capacity() == 0);
+
+ for (int i = 0; i < 10; ++i)
+ v1.push_back(i);
+ v2 = std::move(v1);
+ VERIFY(v2.size() == 10);
+ v2.reserve(50);
+ v1.push_back(1);
+ v2 = std::move(v1);
+ VERIFY(v2.size() == 1);
+ VERIFY(v1.capacity() == 0);
+ VERIFY(v2.capacity() == capacity_for(1));
+
+ std::vector<bool, Alloc<bool>> va1(Alloc<bool>(1)), va2(Alloc<bool>(2));
+ va2 = std::move(va1);
+ VERIFY( va2.get_allocator().personality == 2 );
+ va1.push_back(9);
+ va1.push_back(99);
+ va1.push_back(999);
+ va1.push_back(9999);
+ va2 = std::move(va1);
+ va2 = std::move(va1);
+ VERIFY( va2.get_allocator().personality == 2 );
+
+ return true;
+}
+
+static_assert( move_assign() );
+
+constexpr bool
+initializer_list_assign()
+{
+ std::vector<bool> v1;
+ v1 = {1, 0, 1};
+ VERIFY( v1.size() == 3 );
+ VERIFY( v1.capacity() == capacity_for(3) );
+ v1 = {1, 0};
+ VERIFY( v1.size() == 2 );
+ VERIFY( v1.capacity() == capacity_for(3) );
+ v1 = {1, 1, 0, 1, 1, 1, 0, 1, 1};
+ VERIFY( v1.size() == 9 );
+ VERIFY( v1.capacity() == capacity_for(9) );
+
+ std::vector<bool, Alloc<bool>> va1(Alloc<bool>(111));
+ va1 = {1, 0, 0};
+ VERIFY( va1.get_allocator().personality == 111 );
+
+ return true;
+}
+
+static_assert( initializer_list_assign() );
+
+constexpr bool
+assign_iterator_range()
+{
+ std::vector<bool> v;
+
+ int arr[] = { 1, 2, 3, 4 };
+ v.assign(arr, arr+3);
+ VERIFY( v.size() == 3 );
+ v.reserve(5);
+ v.assign(arr, arr+3);
+ VERIFY( v.capacity() == capacity_for(5) );
+
+ struct input_iterator
+ {
+ using iterator_category = std::input_iterator_tag;
+ using value_type = bool;
+ using pointer = const bool*;
+ using reference = bool;
+ using difference_type = int;
+
+ constexpr input_iterator() : val(0) { }
+ constexpr input_iterator(int i) : val(i) { }
+
+ constexpr input_iterator& operator++() { --val; return *this; }
+ constexpr input_iterator operator++(int) { return {val--}; }
+
+ constexpr bool operator*() const { return val % 2; }
+ constexpr const bool* operator->() const { return nullptr; }
+
+ constexpr bool operator==(const input_iterator&) const = default;
+
+ int val;
+ };
+
+ v.assign(input_iterator(9), input_iterator());
+ VERIFY( v.size() == 9 );
+
+ return true;
+}
+
+static_assert( assign_iterator_range() );
+
+constexpr bool
+assign_value()
+{
+ std::vector<bool> v1;
+ v1.assign(3, 8);
+ VERIFY( v1.size() == 3 );
+ VERIFY( v1.capacity() == capacity_for(3) );
+ v1.assign(2, 9);
+ VERIFY( v1.size() == 2 );
+ VERIFY( v1.capacity() == capacity_for(3) );
+ v1.assign(9, 10);
+ VERIFY( v1.size() == 9 );
+ VERIFY( v1.capacity() == capacity_for(9) );
+
+ std::vector<bool, Alloc<bool>> va1(Alloc<bool>(111));
+ va1.assign(2, 9);
+ VERIFY( va1.size() == 2 );
+ VERIFY( va1.get_allocator().personality == 111 );
+
+ return true;
+}
+
+static_assert( assign_value() );
+
+constexpr bool
+assign_initializer_list()
+{
+ std::vector<bool> v1;
+ v1.assign({0, 1, 0});
+ VERIFY( v1.size() == 3 );
+ VERIFY( v1.capacity() == capacity_for(3) );
+ v1.assign({1, 0});
+ VERIFY( v1.size() == 2 );
+ VERIFY( v1.capacity() == capacity_for(3) );
+ v1.assign({1, 0, 0, 1, 1, 0, 0, 1, 1});
+ VERIFY( v1.size() == 9 );
+ VERIFY( v1.capacity() == capacity_for(9) );
+
+ std::vector<bool, Alloc<bool>> va1(Alloc<bool>(111));
+ va1.assign({1, 1, 1});
+ VERIFY( va1.get_allocator().personality == 111 );
+
+ return true;
+}
+
+static_assert( assign_initializer_list() );
diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/constexpr.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/constexpr.cc
new file mode 100644
index 0000000..b27df2b
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/constexpr.cc
@@ -0,0 +1,248 @@
+// { dg-options "-std=gnu++20" }
+// { dg-do compile { target c++20 } }
+// { dg-xfail-if "not supported" { debug-mode } }
+
+#include <vector>
+#include <testsuite_hooks.h>
+
+template<typename T>
+struct Alloc : std::allocator<T>
+{
+ using std::allocator<T>::allocator;
+
+ constexpr explicit Alloc(int p) : personality(p) { }
+
+ template<typename U>
+ constexpr Alloc(const Alloc<U>& a) : personality(a.personality) { }
+
+ int personality = 0;
+
+ constexpr bool operator==(const Alloc& a) const noexcept
+ { return personality == a.personality; }
+};
+
+constexpr bool
+test_push_back()
+{
+ std::vector<bool> v;
+ std::vector<bool>::reference r = v.emplace_back("");
+ VERIFY( r == true );
+ v.emplace_back(r);
+ VERIFY( v.back() == true );
+ v.emplace_back(v.front());
+ VERIFY( v.back() == true );
+ v.resize(64);
+ v.emplace_back(v.back());
+ VERIFY( v.back() == false );
+ VERIFY( v.size() == 65 );
+ v.emplace_back(8);
+ VERIFY( v.size() == 66 );
+ VERIFY( v.back() == true );
+ v.emplace_back();
+ VERIFY( v.size() == 67 );
+ VERIFY( v.back() == false );
+
+ v.pop_back();
+ VERIFY( v.size() == 66 );
+ VERIFY( v.back() == true );
+ for (int i = 0, n = v.size(); i < n; ++i)
+ v.pop_back();
+ VERIFY( v.empty() );
+
+ v.push_back(true);
+ for (std::size_t i = 0, c = v.capacity(); i <= c; ++i)
+ v.push_back(v.front());
+ VERIFY( v.capacity() > v.size() );
+
+ std::vector<bool, Alloc<bool>> va;
+ va.push_back(true);
+ va.push_back(va.front());
+ VERIFY( va.size() == 2 );
+
+ return true;
+}
+
+static_assert( test_push_back() );
+
+template<typename T = bool>
+constexpr std::false_type
+pop_back_empty() { return {}; }
+
+template<typename T = bool>
+requires (std::bool_constant<(std::vector<T>().pop_back(), true)>::value)
+constexpr std::true_type
+pop_back_empty() { return {}; }
+
+static_assert( ! pop_back_empty() );
+
+constexpr bool
+test_insert_erase()
+{
+ std::vector<bool> v;
+
+ // vector::emplace(const_iterator, Args&&...)
+ auto p = v.emplace(v.begin());
+ VERIFY( p == v.begin() );
+ p = v.emplace(v.end(), '7');
+ VERIFY( p == --v.end() );
+
+ // vector::insert(const_iterator, const T&)
+ p = v.insert(v.begin(), *p);
+ VERIFY( p == v.begin() );
+ VERIFY( *p );
+ // vector::insert(const_iterator, T&&)
+ p = v.insert(v.end(), 1);
+ VERIFY( p == --v.end() );
+ v.insert(p, v.front());
+ v.insert(v.end(), v.back());
+ VERIFY( v.size() == 6 );
+ v.insert(v.end(), true);
+ VERIFY( v.size() == 7 );
+ VERIFY( v.back() == true );
+
+ // vector::insert(const_iterator, size_type, const T&)
+ v.insert(v.begin(), 2, v.front());
+ v.insert(v.end(), 3, 99);
+ VERIFY( v.size() == 12 );
+
+ struct input_iterator
+ {
+ using iterator_category = std::input_iterator_tag;
+ using value_type = bool;
+ using pointer = const bool*;
+ using reference = bool;
+ using difference_type = int;
+
+ constexpr input_iterator() : val(0) { }
+ constexpr input_iterator(int i) : val(i) { }
+
+ constexpr input_iterator& operator++() { --val; return *this; }
+ constexpr input_iterator operator++(int) { return {val--}; }
+
+ constexpr bool operator*() const { return val % 2; }
+ constexpr const bool* operator->() const { return nullptr; }
+
+ constexpr bool operator==(const input_iterator&) const = default;
+
+ int val;
+ };
+
+ // vector::insert(const_iterator, Iter, Iter);
+ v.insert(v.begin() + 2, input_iterator(), input_iterator());
+ VERIFY( v.size() == 12 );
+ v.insert(v.end() - 9, input_iterator(18), input_iterator());
+ VERIFY( v.size() == 30 );
+ short a[] = { false, true };
+ v.insert(v.end(), a, a + 2);
+ VERIFY( v.size() == 32 );
+
+ // vector::insert(const_iterator, initializer_list<T>)
+ v.insert(v.begin(), {1,1,1});
+ VERIFY( v.size() == 35 );
+
+ // vector::erase(const_iterator)
+ v.erase(v.end() - 1);
+ VERIFY( v.size() == 34 );
+ VERIFY( v.back() == false );
+ v.erase(v.begin());
+ v.erase(v.begin() + 1);
+ v.erase(v.end() - 1);
+ VERIFY( v.size() == 31 );
+
+ // vector::erase(const_iterator, const_iterator)
+ v.erase(v.begin(), v.begin());
+ v.erase(v.end(), v.end());
+ v.erase(v.begin(), v.begin() + 1);
+ VERIFY( v.size() == 30 );
+ v.erase(v.begin() + 2, v.end() - 2);
+ VERIFY( v.size() == 4 );
+ v.erase(v.begin(), v.end());
+ VERIFY( v.empty() );
+ v.erase( v.begin(), v.begin() );
+ VERIFY( v.empty() );
+
+ v.insert(v.end(), 99);
+ for (std::size_t i = 0, c = v.capacity(); i <= c; ++i)
+ v.insert(v.end() - 1, v.front());
+ VERIFY( v.capacity() > v.size() );
+ v.insert(v.end(), 999);
+ for (std::size_t i = 0, c = v.capacity(); i <= c; ++i)
+ v.insert(v.begin(), v.front());
+
+ std::vector<bool, Alloc<bool>> va;
+ va.insert(va.begin(), 99);
+ va.insert(va.begin(), va.front());
+ VERIFY( va.size() == 2 );
+ va.erase(va.begin());
+
+ return true;
+}
+
+static_assert( test_insert_erase() );
+
+constexpr std::size_t
+capacity_for(std::size_t n)
+{
+ std::size_t N = std::vector<bool>(1).capacity();
+ if (auto r = n % N)
+ return n - r + N;
+ return n;
+}
+
+constexpr bool
+test_clear()
+{
+ std::vector<bool> v0;
+ v0.clear();
+ VERIFY( v0.size() == 0 );
+ VERIFY( v0.capacity() == 0 );
+
+ std::vector<bool> v{1, 0, 0};
+ v.clear();
+ VERIFY( v.size() == 0 );
+ VERIFY( v.capacity() == capacity_for(3) );
+
+ std::vector<bool, Alloc<bool>> va;
+ va.clear();
+ va.push_back(1);
+ va.clear();
+ va.clear();
+
+ return true;
+}
+
+static_assert( test_clear() );
+
+constexpr bool
+test_flip()
+{
+ std::vector<bool> v{1, 0, 0, 1, 0, 1, 1, 0};
+ v.flip();
+ VERIFY( !v[0] && v[1] && v[2] && !v[3] && v[4] && !v[5] && !v[6] && v[7] );
+ v[2].flip();
+ VERIFY( !v[2] );
+ v[2].flip();
+ VERIFY( v[2] );
+
+ return true;
+}
+
+static_assert( test_flip() );
+
+constexpr bool
+test_erasure()
+{
+ std::vector<bool> e{true,true,true,false,true,false};
+
+ auto n = std::erase(e, false);
+ VERIFY( n == 2 );
+ VERIFY( e.size() == 4 );
+ e[2] = false;
+ n = std::erase_if(e, [](std::vector<bool>::reference val) { return !val; });
+ VERIFY( n == 1 );
+ VERIFY( e.size() == 3 );
+
+ return true;
+}
+
+static_assert( test_erasure() );
diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/insert/31370.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/insert/31370.cc
index a2b8c1a..c679446 100644
--- a/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/insert/31370.cc
+++ b/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/insert/31370.cc
@@ -24,11 +24,7 @@
#include <stdexcept>
#include <testsuite_hooks.h>
-#ifdef _GLIBCXX_DEBUG
- using std::_GLIBCXX_STD_C::_S_word_bit;
-#else
- using std::_S_word_bit;
-#endif
+using std::_S_word_bit;
inline void
check_cap_ge_size(const std::vector<bool>& x)
diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/swap/constexpr.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/swap/constexpr.cc
new file mode 100644
index 0000000..ba444d0
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/swap/constexpr.cc
@@ -0,0 +1,66 @@
+// { dg-options "-std=gnu++20" }
+// { dg-do compile { target c++20 } }
+// { dg-xfail-if "not supported" { debug-mode } }
+
+#include <vector>
+#include <utility>
+#include <testsuite_hooks.h>
+
+constexpr bool
+test_std_swap()
+{
+ std::vector<bool> v1 = {true, false, true};
+ std::vector<bool> v2 = {false, true};
+
+ std::swap(v1, v2);
+
+ VERIFY(v1.size() == 2);
+ VERIFY(v1.at(0) == false);
+ VERIFY(v1.at(1) == true);
+
+ VERIFY(v2.size() == 3);
+ VERIFY(v2[0]);
+ VERIFY(!v2[1]);
+ VERIFY(v2[2]);
+
+ return true;
+}
+
+static_assert(test_std_swap());
+
+constexpr bool
+test_member_swap()
+{
+ std::vector<bool> v1 = {true, false, true};
+ std::vector<bool> v2 = {false, true};
+
+ v1.swap(v2);
+
+ VERIFY(v1.size() == 2);
+ VERIFY(v1.at(0) == false);
+ VERIFY(v1.at(1) == true);
+
+ VERIFY(v2.size() == 3);
+ VERIFY(v2[0]);
+ VERIFY(!v2[1]);
+ VERIFY(v2[2]);
+
+ return true;
+}
+
+static_assert(test_member_swap());
+
+constexpr bool
+test_reference_swap()
+{
+ std::vector<bool> v1 = {true, false, true};
+ std::vector<bool>::swap(v1[0], v1[1]);
+
+ VERIFY(v1[0] == false);
+ VERIFY(v1[1] == true);
+ VERIFY(v1[2] == true);
+
+ return true;
+}
+
+static_assert(test_reference_swap());
diff --git a/libstdc++-v3/testsuite/23_containers/vector/capacity/constexpr.cc b/libstdc++-v3/testsuite/23_containers/vector/capacity/constexpr.cc
new file mode 100644
index 0000000..de9d0b0
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/vector/capacity/constexpr.cc
@@ -0,0 +1,101 @@
+// { dg-options "-std=gnu++20" }
+// { dg-do compile { target c++20 } }
+// { dg-xfail-if "not supported" { debug-mode } }
+
+#include <vector>
+#include <testsuite_hooks.h>
+
+constexpr bool
+test_empty()
+{
+ std::vector<int> v;
+ VERIFY( v.empty() );
+ v = {1};
+ VERIFY( !v.empty() );
+
+ return true;
+}
+
+static_assert( test_empty() );
+
+constexpr bool
+test_size()
+{
+ std::vector<int> v;
+ VERIFY( v.size() == 0 );
+ v = {1};
+ VERIFY( v.size() == 1 );
+
+ VERIFY( v.max_size() != 0 );
+
+ return true;
+}
+
+static_assert( test_size() );
+
+constexpr bool
+test_capacity()
+{
+ std::vector<int> v;
+ VERIFY( v.size() == 0 );
+ VERIFY( v.capacity() == v.size() );
+ v = {1, 2, 3};
+ VERIFY( v.size() == 3 );
+ VERIFY( v.capacity() == v.size() );
+
+ return true;
+}
+
+static_assert( test_capacity() );
+
+constexpr bool
+test_resize()
+{
+ std::vector<int> v;
+ v.reserve(9);
+ VERIFY( v.size() == 0 );
+ VERIFY( v.capacity() == 9 );
+ v.resize(5);
+ VERIFY( v.size() == 5 );
+ VERIFY( v.capacity() == 9 );
+ v.resize(15, 6);
+ VERIFY( v.size() == 15 );
+ VERIFY( v[10] == 6 );
+
+ return true;
+}
+
+static_assert( test_resize() );
+
+constexpr bool
+test_reserve()
+{
+ std::vector<int> v;
+ v.reserve(9);
+ VERIFY( v.size() == 0 );
+ VERIFY( v.capacity() == 9 );
+ v.resize(2);
+ VERIFY( v.size() == 2 );
+ VERIFY( v.capacity() == 9 );
+
+ return true;
+}
+
+static_assert( test_reserve() );
+
+constexpr bool
+test_shrink_to_fit()
+{
+ std::vector<int> v;
+ v.reserve(9);
+ v.shrink_to_fit();
+ VERIFY( v.capacity() == 0 );
+ v.reserve(9);
+ v.resize(5);
+ v.shrink_to_fit();
+ VERIFY( v.capacity() == v.size() );
+
+ return true;
+}
+
+static_assert( test_shrink_to_fit() );
diff --git a/libstdc++-v3/testsuite/23_containers/vector/cmp_c++20.cc b/libstdc++-v3/testsuite/23_containers/vector/cmp_c++20.cc
index 0ffacb9..8f4a264 100644
--- a/libstdc++-v3/testsuite/23_containers/vector/cmp_c++20.cc
+++ b/libstdc++-v3/testsuite/23_containers/vector/cmp_c++20.cc
@@ -16,12 +16,13 @@
// <http://www.gnu.org/licenses/>.
// { dg-options "-std=gnu++2a" }
-// { dg-do run { target c++2a } }
+// { dg-do compile { target c++2a } }
+// { dg-xfail-if "not supported" { debug-mode } }
#include <vector>
#include <testsuite_hooks.h>
-void
+constexpr bool
test01()
{
std::vector<int> c1{ 1, 2, 3 }, c2{ 1, 2, 3, 4 }, c3{ 1, 2, 4 };
@@ -47,24 +48,26 @@ test01()
struct E
{
- bool operator==(E) { return true; }
+ constexpr bool operator==(E) const { return true; }
};
static_assert( ! std::totally_ordered<std::vector<E>> );
static_assert( ! std::three_way_comparable<E> );
static_assert( ! std::three_way_comparable<std::vector<E>> );
+
+ return true;
}
-void
+constexpr bool
test02()
{
struct W
{
int value = 0;
- bool operator==(W rhs) const noexcept
+ constexpr bool operator==(W rhs) const noexcept
{ return (value | 1) == (rhs.value | 1); }
- std::weak_ordering
+ constexpr std::weak_ordering
operator<=>(W rhs) const noexcept
{ return (value | 1) <=> (rhs.value | 1); }
};
@@ -75,23 +78,25 @@ test02()
static_assert( std::same_as<decltype(c1 <=> c1), std::weak_ordering> );
VERIFY( c1 == c2 );
VERIFY( std::is_eq(c1 <=> c2) );
+
+ return true;
}
-void
+constexpr bool
test03()
{
struct P
{
int value = 0;
- bool operator==(P rhs) const noexcept
+ constexpr bool operator==(P rhs) const noexcept
{
if (value < 0 || rhs.value < 0)
return false;
return value == rhs.value;
}
- std::partial_ordering
+ constexpr std::partial_ordering
operator<=>(P rhs) const noexcept
{
if (value < 0 || rhs.value < 0)
@@ -106,16 +111,18 @@ test03()
static_assert( std::three_way_comparable<P> );
static_assert( std::same_as<decltype(c <=> c), std::partial_ordering> );
VERIFY( (c <=> c) == std::partial_ordering::unordered );
+
+ return true;
}
-void
+constexpr bool
test04()
{
struct L
{
int value = 0;
- bool operator<(L rhs) const noexcept { return value < rhs.value; }
+ constexpr bool operator<(L rhs) const noexcept { return value < rhs.value; }
};
static_assert( std::totally_ordered<std::vector<L>> );
@@ -123,9 +130,11 @@ test04()
std::vector<L> c{ {1}, {2}, {3} }, d{ {1}, {2}, {3}, {4} };
static_assert( std::same_as<decltype(c <=> c), std::weak_ordering> );
VERIFY( std::is_lt(c <=> d) );
+
+ return true;
}
-void
+constexpr bool
test05()
{
// vector iterators are random access, so should support <=>
@@ -148,14 +157,12 @@ test05()
static_assert( std::same_as<decltype(c.begin() <=> c.begin()),
std::strong_ordering> );
-}
-int
-main()
-{
- test01();
- test02();
- test03();
- test04();
- test05();
+ return true;
}
+
+static_assert( test01() );
+static_assert( test02() );
+static_assert( test03() );
+static_assert( test04() );
+static_assert( test05() );
diff --git a/libstdc++-v3/testsuite/23_containers/vector/cons/89164.cc b/libstdc++-v3/testsuite/23_containers/vector/cons/89164.cc
index 302af9c..4f8396f 100644
--- a/libstdc++-v3/testsuite/23_containers/vector/cons/89164.cc
+++ b/libstdc++-v3/testsuite/23_containers/vector/cons/89164.cc
@@ -31,20 +31,18 @@ void test01()
{
X x[1];
// Should not be able to create vector using uninitialized_copy:
- std::vector<X> v1{x, x+1}; // { dg-error "here" }
-
- // Should not be able to create vector using uninitialized_fill_n:
- std::vector<X> v2{2u, X{}}; // { dg-error "here" }
+ std::vector<X> v1{x, x+1}; // { dg-error "here" "" { target c++17_down } }
+ // { dg-error "deleted function 'X::X" "" { target c++20 } 0 }
}
void test02()
{
-#if __cplusplus >= 201703L
struct Y : X { };
- // Can create initializer_list<Y> with C++17 guaranteed copy elision,
- // but shouldn't be able to copy from it with uninitialized_copy:
- std::vector<Y> v3{Y{}, Y{}, Y{}}; // { dg-error "here" "" { target c++17 } }
-#endif
+
+ // Should not be able to create vector using uninitialized_fill_n:
+ std::vector<Y> v2{2u, Y{}}; // { dg-error "here" "" { target c++17_down } }
+ // { dg-error "deleted function .*Y::Y" "" { target c++20 } 0 }
}
// { dg-error "must be constructible from input type" "" { target *-*-* } 0 }
+// { dg-prune-output "construct_at" }
diff --git a/libstdc++-v3/testsuite/23_containers/vector/cons/89164_c++17.cc b/libstdc++-v3/testsuite/23_containers/vector/cons/89164_c++17.cc
new file mode 100644
index 0000000..24ade4e
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/vector/cons/89164_c++17.cc
@@ -0,0 +1,39 @@
+// Copyright (C) 2019-2021 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do compile { target c++17 } }
+
+#include <vector>
+
+// PR libstdc++/89164
+
+struct X
+{
+ X() = default;
+ X(const X&) = delete;
+};
+
+void test03()
+{
+ // Can create initializer_list<Y> with C++17 guaranteed copy elision,
+ // but shouldn't be able to copy from it with uninitialized_copy:
+ std::vector<X> v3{X{}, X{}, X{}}; // { dg-error "here" "" { target c++17_only } }
+ // { dg-error "deleted function .*X::X" "" { target c++20 } 0 }
+}
+
+// { dg-error "must be constructible from input type" "" { target *-*-* } 0 }
+// { dg-prune-output "construct_at" }
diff --git a/libstdc++-v3/testsuite/23_containers/vector/cons/constexpr.cc b/libstdc++-v3/testsuite/23_containers/vector/cons/constexpr.cc
new file mode 100644
index 0000000..f02b39a
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/vector/cons/constexpr.cc
@@ -0,0 +1,279 @@
+// { dg-options "-std=gnu++20" }
+// { dg-do compile { target c++20 } }
+// { dg-xfail-if "not supported" { debug-mode } }
+
+#include <vector>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+template<typename T>
+struct Alloc : std::allocator<T>
+{
+ using std::allocator<T>::allocator;
+
+ constexpr explicit Alloc(int p) : personality(p) { }
+
+ template<typename U>
+ constexpr Alloc(const Alloc<U>& a) : personality(a.personality) { }
+
+ int personality = 0;
+
+ constexpr Alloc select_on_container_copy_construction() const
+ { return Alloc(-1); }
+
+ constexpr bool operator==(const Alloc& a) const noexcept
+ { return personality == a.personality; }
+};
+
+namespace default_constructor_global_scope
+{
+ constexpr std::vector<int> v1;
+ static_assert(v1.size() == 0);
+ static_assert(v1.capacity() == 0);
+
+ constexpr std::allocator<int> a;
+ constexpr std::vector<int> v2(a);
+ static_assert(v2.size() == 0);
+ static_assert(v2.capacity() == 0);
+
+ constexpr Alloc<int> aa(10);
+ constexpr std::vector<int, Alloc<int>> v3(aa);
+ static_assert(v3.size() == 0);
+ static_assert(v3.capacity() == 0);
+ static_assert(v3.get_allocator() == aa);
+}
+
+constexpr bool
+default_constructor_function_scope()
+{
+ // vector()
+
+ std::vector<int> v1;
+ VERIFY(v1.size() == 0);
+ VERIFY(v1.capacity() == 0);
+
+ // vector(const Allocator&)
+
+ const std::allocator<int> a;
+ std::vector<int> v2(a);
+ VERIFY(v2.size() == 0);
+ VERIFY(v2.capacity() == 0);
+
+ const Alloc<long> aa(10);
+ std::vector<long, Alloc<long>> v3(aa);
+ VERIFY(v3.size() == 0);
+ VERIFY(v3.capacity() == 0);
+ VERIFY(v3.get_allocator() == aa);
+
+ return true;
+}
+
+static_assert( default_constructor_function_scope() );
+
+constexpr bool
+sequence_constructors()
+{
+ // vector(size_type, const Allocator& = Allocator())
+
+ std::vector<int> v0(0);
+ VERIFY(v0.size() == 0);
+
+ std::vector<int> v1(1);
+ VERIFY(v1.size() == 1);
+
+ std::vector<int> v2(2);
+ VERIFY(v2.size() == 2);
+
+ std::vector<int> v50(50);
+ VERIFY(v50.size() == 50);
+
+ const std::allocator<int> a;
+ std::vector<int> a0(0, a);
+ VERIFY(a0.size() == 0);
+
+ std::vector<int> a1(1, a);
+ VERIFY(a1.size() == 1);
+
+ std::vector<int> a2(2, a);
+ VERIFY(a2.size() == 2);
+
+ std::vector<int> a50(50, a);
+ VERIFY(a50.size() == 50);
+
+ const Alloc<long> la(10);
+ std::vector<long, Alloc<long>> l0(0, la);
+ VERIFY(l0.size() == 0);
+ VERIFY(l0.get_allocator() == la);
+
+ std::vector<long, Alloc<long>> l1(1, la);
+ VERIFY(l1.size() == 1);
+ VERIFY(l1.get_allocator() == la);
+
+ std::vector<long, Alloc<long>> l2(2, la);
+ VERIFY(l2.size() == 2);
+ VERIFY(l2.get_allocator() == la);
+
+ std::vector<long, Alloc<long>> l50(50, la);
+ VERIFY(l50.size() == 50);
+ VERIFY(l50.get_allocator() == la);
+
+ // vector(size_type, const T&, const Allocator& = Allocator())
+
+ std::vector<int> v3(3, 4);
+ VERIFY(v3.size() == 3);
+ VERIFY(v3[0] == 4 && v3[2] == 4);
+
+ std::vector<int> a3(3, 5, a);
+ VERIFY(a3.size() == 3);
+ VERIFY(a3[0] == 5 && a3[2] == 5);
+
+ std::vector<long, Alloc<long>> l3(3, 6, la);
+ VERIFY(l3.size() == 3);
+ VERIFY(l3[0] == 6 && l3[2] == 6);
+ VERIFY(l3.get_allocator() == la);
+
+ return true;
+}
+
+static_assert(sequence_constructors());
+
+constexpr bool
+iterator_range_constructor()
+{
+ // vector(InputIterator, InputIterator, const Allocator& = Allocator())
+
+ short range[3] = { 1, 2, 3 };
+
+ std::vector<int> v0(std::begin(range), std::end(range));
+ VERIFY(v0.size() == std::size(range));
+ VERIFY(v0[0] == 1 && v0[1] == 2 && v0[2] == 3);
+
+ const Alloc<long> a(5);
+ std::vector<long, Alloc<long>> l0(std::begin(range), std::end(range), a);
+ VERIFY(l0.size() == std::size(range));
+ VERIFY(l0.get_allocator() == a);
+ VERIFY(l0[0] == 1 && l0[1] == 2 && l0[2] == 3);
+
+ struct input_iterator
+ {
+ using iterator_category = std::input_iterator_tag;
+ using value_type = int;
+ using pointer = const int*;
+ using reference = int;
+ using difference_type = int;
+
+ constexpr input_iterator() : val(0) { }
+ constexpr input_iterator(int i) : val(i) { }
+
+ constexpr input_iterator& operator++() { --val; return *this; }
+ constexpr input_iterator operator++(int) { return {val--}; }
+
+ constexpr int operator*() const { return val; }
+ constexpr const int* operator->() const { return &val; }
+
+ constexpr bool operator==(const input_iterator&) const = default;
+
+ int val;
+ };
+
+ std::vector<int> v1(input_iterator(3), input_iterator());
+ VERIFY(v1.size() == 3);
+ VERIFY(v1[0] == 3 && v1[1] == 2 && v1[2] == 1);
+
+ std::vector<long, Alloc<long>> l1(input_iterator(2), input_iterator(), a);
+ VERIFY(l1.size() == 2);
+ VERIFY(l1.get_allocator() == a);
+ VERIFY(l1[0] == 2 && l1[1] == 1);
+
+ return true;
+}
+
+static_assert(iterator_range_constructor());
+
+constexpr bool
+initializer_list_constructor()
+{
+ // vector(initializer_list<T>, const Allocator& = Allocator())
+
+ std::vector<int> v0({ 1, 2, 3 });
+ VERIFY(v0.size() == 3);
+ VERIFY(v0[0] == 1 && v0[1] == 2 && v0[2] == 3);
+
+ const Alloc<long> a(5);
+ std::vector<long, Alloc<long>> l0({ 1, 2, 3 }, a);
+ VERIFY(l0.size() == 3);
+ VERIFY(l0.get_allocator() == a);
+
+ return true;
+}
+
+static_assert(initializer_list_constructor());
+
+constexpr bool
+copy_constructor()
+{
+ const std::vector<int> v0({ 1, 2, 3 });
+ const std::vector<long, Alloc<long>> l0({ 4, 5, 6 });
+
+ // vector(const vector&)
+
+ std::vector<int> v1(v0);
+ VERIFY( v1.size() == v0.size() );
+ VERIFY( v1[0] == v0[0] && v1[1] == v0[1] && v1[2] == v0[2] );
+ VERIFY( v1.get_allocator() == v0.get_allocator() );
+
+ const Alloc<short> as(6);
+ std::vector<short, Alloc<short>> s1(3, short(2), as);
+ std::vector<short, Alloc<short>> s2(s1);
+ VERIFY( s2.size() == s1.size() );
+ VERIFY( s2.get_allocator().personality == -1 );
+
+ // vector(const vector&, const Allocator&)
+
+ const Alloc<long> a(6);
+ std::vector<long, Alloc<long>> l1(l0, a);
+ VERIFY( l1.size() == l0.size() );
+ VERIFY( l1[0] == l0[0] && l1[1] == l0[1] && l1[2] == l0[2] );
+ VERIFY( l1.get_allocator() == a );
+ VERIFY( l1.get_allocator() != l0.get_allocator() );
+
+ return true;
+}
+
+static_assert(copy_constructor());
+
+constexpr bool
+move_constructor()
+{
+ const std::vector<int> v0({ 1, 2, 3 });
+ const std::vector<long, Alloc<long>> l0({ 4, 5, 6 });
+
+ // vector(const vector&)
+
+ std::vector<int> v1(v0);
+ std::vector<int> v2(std::move(v1));
+ VERIFY( v2.size() == v0.size() );
+ VERIFY( v1.empty() );
+ VERIFY( v2[0] == v0[0] && v2[1] == v0[1] && v2[2] == v0[2] );
+ VERIFY( v2.get_allocator() == v0.get_allocator() );
+
+ // vector(const vector&, const Allocator&)
+
+ const Alloc<long> a(6);
+ std::vector<long, Alloc<long>> l1(l0);
+ std::vector<long, Alloc<long>> l2(std::move(l1), a);
+ VERIFY( l2.size() == l0.size() );
+ VERIFY( l2[0] == l0[0] && l2[1] == l0[1] && l2[2] == l0[2] );
+ VERIFY( l2.get_allocator() == a );
+ VERIFY( l2.get_allocator() != l0.get_allocator() );
+
+ std::vector<long, Alloc<long>> l3(std::move(l2), a);
+ VERIFY( l3.size() == l0.size() );
+ VERIFY( l3[0] == l0[0] && l3[1] == l0[1] && l3[2] == l0[2] );
+ VERIFY( l3.get_allocator() == a );
+ VERIFY( l3.get_allocator() == l2.get_allocator() );
+
+ return true;
+}
+
+static_assert(move_constructor());
diff --git a/libstdc++-v3/testsuite/23_containers/vector/data_access/constexpr.cc b/libstdc++-v3/testsuite/23_containers/vector/data_access/constexpr.cc
new file mode 100644
index 0000000..45b3167
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/vector/data_access/constexpr.cc
@@ -0,0 +1,26 @@
+// { dg-options "-std=gnu++20" }
+// { dg-do compile { target c++20 } }
+// { dg-xfail-if "not supported" { debug-mode } }
+
+#include <vector>
+#include <testsuite_hooks.h>
+
+constexpr bool
+test_data()
+{
+ std::vector<int> v;
+ VERIFY( v.data() == nullptr );
+ v.reserve(1);
+ VERIFY( v.data() != nullptr );
+ const std::vector<int> v2{1,3,5,9};
+ VERIFY( v.data() != v2.data() );
+ VERIFY( v2.data()[2] == 5 );
+
+ v = v2;
+ VERIFY( v.data() != v2.data() );
+ VERIFY( v.data()[1] == 3 );
+
+ return true;
+}
+
+static_assert(test_data());
diff --git a/libstdc++-v3/testsuite/23_containers/vector/element_access/constexpr.cc b/libstdc++-v3/testsuite/23_containers/vector/element_access/constexpr.cc
new file mode 100644
index 0000000..9b3b7f63
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/vector/element_access/constexpr.cc
@@ -0,0 +1,91 @@
+// { dg-options "-std=gnu++20" }
+// { dg-do compile { target c++20 } }
+// { dg-xfail-if "not supported" { debug-mode } }
+
+#include <vector>
+#include <testsuite_hooks.h>
+
+constexpr bool
+test_iterators()
+{
+ std::vector<int> v;
+ VERIFY( v.begin() == v.end() );
+ v.reserve(1);
+ VERIFY( v.begin() == v.end() );
+ v.resize(2);
+ VERIFY( v.begin() != v.end() );
+ VERIFY( v.cbegin() == v.begin() );
+ VERIFY( v.crbegin() == v.rbegin() );
+ VERIFY( v.cend() == v.end() );
+ VERIFY( v.crend() == v.rend() );
+
+ auto it = v.begin();
+ VERIFY( &*it == &v.front() );
+ VERIFY( it++ == v.begin() );
+ VERIFY( ++it == v.end() );
+ VERIFY( (it - 2) == v.begin() );
+ it -= 2;
+ it += 1;
+ VERIFY( (it + 1) == v.end() );
+
+ auto rit = v.rbegin();
+ VERIFY( &*rit == &v.back() );
+ VERIFY( rit++ == v.rbegin() );
+ VERIFY( ++rit == v.rend() );
+ VERIFY( (rit - 2) == v.rbegin() );
+ rit -= 2;
+ rit += 1;
+ VERIFY( (rit + 1) == v.rend() );
+
+ return true;
+}
+
+static_assert(test_iterators());
+
+constexpr bool
+test_access()
+{
+ std::vector<int> v{1, 2, 3};
+ VERIFY( v.at(1) == 2 );
+ VERIFY( v[2] == 3 );
+ VERIFY( &v[2] == &v.at(2) );
+ VERIFY( &v.front() == &v[0] );
+ VERIFY( &v.back() == &v[2] );
+
+ const auto& vc = v;
+ VERIFY( vc.at(1) == 2 );
+ VERIFY( &vc.at(1) == &v.at(1) );
+ VERIFY( &vc.at(1) == &vc[1] );
+ VERIFY( &vc.front() == &vc[0] );
+ VERIFY( &vc.back() == &vc[2] );
+
+ return true;
+}
+
+static_assert(test_access());
+
+template<typename T = int>
+ constexpr std::false_type
+ access_empty() { return {}; }
+
+template<typename T = int>
+ requires (std::bool_constant<(std::vector<T>().at(0), true)>::value)
+ constexpr std::true_type
+ access_empty() { return {}; }
+
+template<typename T = int>
+ requires (std::bool_constant<(std::vector<T>()[0], true)>::value)
+ constexpr std::true_type
+ access_empty() { return {}; }
+
+template<typename T = int>
+ requires (std::bool_constant<(std::vector<T>().front(), true)>::value)
+ constexpr std::true_type
+ access_empty() { return {}; }
+
+template<typename T = int>
+ requires (std::bool_constant<(std::vector<T>().back(), true)>::value)
+ constexpr std::true_type
+ access_empty() { return {}; }
+
+static_assert( ! access_empty() );
diff --git a/libstdc++-v3/testsuite/23_containers/vector/modifiers/assign/constexpr.cc b/libstdc++-v3/testsuite/23_containers/vector/modifiers/assign/constexpr.cc
new file mode 100644
index 0000000..638cffe
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/vector/modifiers/assign/constexpr.cc
@@ -0,0 +1,207 @@
+// { dg-options "-std=gnu++20" }
+// { dg-do compile { target c++20 } }
+// { dg-xfail-if "not supported" { debug-mode } }
+
+#include <vector>
+#include <testsuite_hooks.h>
+
+template<typename T>
+struct Alloc : std::allocator<T>
+{
+ using std::allocator<T>::allocator;
+
+ constexpr explicit Alloc(int p) : personality(p) { }
+
+ template<typename U>
+ constexpr Alloc(const Alloc<U>& a) : personality(a.personality) { }
+
+ int personality = 0;
+
+ using propagate_on_container_move_assignment = std::false_type;
+
+ constexpr bool operator==(const Alloc& a) const noexcept
+ { return personality == a.personality; }
+};
+
+constexpr bool
+copy_assign()
+{
+ // vector::operator=(const vector&)
+
+ std::vector<int> v1, v2;
+ v1 = v1;
+ v2 = v1;
+ VERIFY(v2.size() == 0);
+ VERIFY(v2.capacity() == 0);
+
+ for (int i = 0; i < 10; ++i)
+ v1.push_back(i);
+ v2 = v1;
+ VERIFY(v2.size() == 10);
+ v2.reserve(50);
+ v1.push_back(1);
+ v2 = v1;
+ VERIFY(v2.size() == 11);
+ VERIFY(v2.capacity() == 50);
+
+ std::vector<int, Alloc<int>> va1(Alloc<int>(1)), va2(Alloc<int>(2));
+ va2 = va1;
+ VERIFY( va2.get_allocator().personality == 2 );
+ va1.push_back(999);
+ va2 = va1;
+ VERIFY( va2.get_allocator().personality == 2 );
+
+ return true;
+}
+
+static_assert( copy_assign() );
+
+constexpr bool
+move_assign()
+{
+ // vector::operator=(const vector&)
+
+ std::vector<int> v1, v2;
+ v1 = std::move(v1);
+ v2 = std::move(v1);
+ VERIFY(v2.size() == 0);
+ VERIFY(v2.capacity() == 0);
+
+ for (int i = 0; i < 10; ++i)
+ v1.push_back(i);
+ v2 = std::move(v1);
+ VERIFY(v2.size() == 10);
+ v2.reserve(50);
+ v1.push_back(1);
+ v2 = std::move(v1);
+ VERIFY(v2.size() == 1);
+ VERIFY(v1.capacity() == 0);
+ VERIFY(v2.capacity() == 1);
+
+ std::vector<int, Alloc<int>> va1(Alloc<int>(1)), va2(Alloc<int>(2));
+ va2 = std::move(va1);
+ VERIFY( va2.get_allocator().personality == 2 );
+ va1.push_back(9);
+ va1.push_back(99);
+ va1.push_back(999);
+ va1.push_back(9999);
+ va2 = std::move(va1);
+ va2 = std::move(va1);
+ VERIFY( va2.get_allocator().personality == 2 );
+
+ return true;
+}
+
+static_assert( move_assign() );
+
+constexpr bool
+initializer_list_assign()
+{
+ std::vector<int> v1;
+ v1 = {1, 2, 3};
+ VERIFY( v1.size() == 3 );
+ VERIFY( v1.capacity() == 3 );
+ v1 = {1, 2};
+ VERIFY( v1.size() == 2 );
+ VERIFY( v1.capacity() == 3 );
+ v1 = {1, 2, 3, 4, 5, 6, 7, 8, 9};
+ VERIFY( v1.size() == 9 );
+ VERIFY( v1.capacity() == 9 );
+
+ std::vector<int, Alloc<int>> va1(Alloc<int>(111));
+ va1 = {1, 2, 3};
+ VERIFY( va1.get_allocator().personality == 111 );
+
+ return true;
+}
+
+static_assert( initializer_list_assign() );
+
+constexpr bool
+assign_iterator_range()
+{
+ std::vector<int> v;
+
+ int arr[] = { 1, 2, 3, 4 };
+ v.assign(arr, arr+3);
+ VERIFY( v.size() == 3 );
+ v.reserve(5);
+ v.assign(arr, arr+3);
+ VERIFY( v.capacity() == 5 );
+
+ struct input_iterator
+ {
+ using iterator_category = std::input_iterator_tag;
+ using value_type = int;
+ using pointer = const int*;
+ using reference = int;
+ using difference_type = int;
+
+ constexpr input_iterator() : val(0) { }
+ constexpr input_iterator(int i) : val(i) { }
+
+ constexpr input_iterator& operator++() { --val; return *this; }
+ constexpr input_iterator operator++(int) { return {val--}; }
+
+ constexpr int operator*() const { return val; }
+ constexpr const int* operator->() const { return &val; }
+
+ constexpr bool operator==(const input_iterator&) const = default;
+
+ int val;
+ };
+
+ v.assign(input_iterator(9), input_iterator());
+ VERIFY( v.size() == 9 );
+
+ return true;
+}
+
+static_assert( assign_iterator_range() );
+
+constexpr bool
+assign_value()
+{
+ std::vector<int> v1;
+ v1.assign(3, 8);
+ VERIFY( v1.size() == 3 );
+ VERIFY( v1.capacity() == 3 );
+ v1.assign(2, 9);
+ VERIFY( v1.size() == 2 );
+ VERIFY( v1.capacity() == 3 );
+ v1.assign(9, 10);
+ VERIFY( v1.size() == 9 );
+ VERIFY( v1.capacity() == 9 );
+
+ std::vector<int, Alloc<int>> va1(Alloc<int>(111));
+ va1.assign(2, 9);
+ VERIFY( va1.size() == 2 );
+ VERIFY( va1.get_allocator().personality == 111 );
+
+ return true;
+}
+
+static_assert( assign_value() );
+
+constexpr bool
+assign_initializer_list()
+{
+ std::vector<int> v1;
+ v1.assign({1, 2, 3});
+ VERIFY( v1.size() == 3 );
+ VERIFY( v1.capacity() == 3 );
+ v1.assign({1, 2});
+ VERIFY( v1.size() == 2 );
+ VERIFY( v1.capacity() == 3 );
+ v1.assign({1, 2, 3, 4, 5, 6, 7, 8, 9});
+ VERIFY( v1.size() == 9 );
+ VERIFY( v1.capacity() == 9 );
+
+ std::vector<int, Alloc<int>> va1(Alloc<int>(111));
+ va1.assign({1, 2, 3});
+ VERIFY( va1.get_allocator().personality == 111 );
+
+ return true;
+}
+
+static_assert( assign_initializer_list() );
diff --git a/libstdc++-v3/testsuite/23_containers/vector/modifiers/constexpr.cc b/libstdc++-v3/testsuite/23_containers/vector/modifiers/constexpr.cc
new file mode 100644
index 0000000..36efecf
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/vector/modifiers/constexpr.cc
@@ -0,0 +1,226 @@
+// { dg-options "-std=gnu++20" }
+// { dg-do compile { target c++20 } }
+// { dg-xfail-if "not supported" { debug-mode } }
+
+#include <vector>
+#include <testsuite_hooks.h>
+
+template<typename T>
+struct Alloc : std::allocator<T>
+{
+ using std::allocator<T>::allocator;
+
+ constexpr explicit Alloc(int p) : personality(p) { }
+
+ template<typename U>
+ constexpr Alloc(const Alloc<U>& a) : personality(a.personality) { }
+
+ int personality = 0;
+
+ constexpr bool operator==(const Alloc& a) const noexcept
+ { return personality == a.personality; }
+};
+
+constexpr bool
+test_push_back()
+{
+ std::vector<int> v;
+ int& r = v.emplace_back(7);
+ VERIFY( r == 7 );
+ VERIFY( &r == &v.front() );
+ v.emplace_back(r);
+ v.emplace_back(v.front());
+ v.emplace_back(v.back());
+ VERIFY( v.size() == 4 );
+ v.emplace_back(8);
+ VERIFY( v.size() == 5 );
+ VERIFY( v.back() == 8 );
+
+ v.pop_back();
+ VERIFY( v.size() == 4 );
+ VERIFY( v.back() == 7 );
+ v.pop_back();
+ v.pop_back();
+ v.pop_back();
+ v.pop_back();
+ VERIFY( v.empty() );
+
+ v.push_back(99);
+ for (std::size_t i = 0, c = v.capacity(); i <= c; ++i)
+ v.push_back(v.front());
+ VERIFY( v.capacity() > v.size() );
+
+ std::vector<int, Alloc<int>> va;
+ va.push_back(99);
+ va.push_back(va.front());
+ VERIFY( va.size() == 2 );
+
+ return true;
+}
+
+static_assert( test_push_back() );
+
+template<typename T = int>
+constexpr std::false_type
+pop_back_empty() { return {}; }
+
+template<typename T = int>
+requires (std::bool_constant<(std::vector<T>().pop_back(), true)>::value)
+constexpr std::true_type
+pop_back_empty() { return {}; }
+
+static_assert( ! pop_back_empty() );
+
+constexpr bool
+test_insert_erase()
+{
+ std::vector<int> v;
+
+ // vector::emplace(const_iterator, Args&&...)
+ auto p = v.emplace(v.begin());
+ VERIFY( p == v.begin() );
+ p = v.emplace(v.end(), 7);
+ VERIFY( p == --v.end() );
+
+ // vector::insert(const_iterator, const T&)
+ p = v.insert(v.begin(), *p);
+ VERIFY( p == v.begin() );
+ VERIFY( *p == 7 );
+ VERIFY( &*p == &v.front() );
+ // vector::insert(const_iterator, T&&)
+ p = v.insert(v.end(), 1);
+ VERIFY( p == --v.end() );
+ v.insert(p, v.front());
+ v.insert(v.end(), v.back());
+ VERIFY( v.size() == 6 );
+ v.insert(v.end(), 8);
+ VERIFY( v.size() == 7 );
+ VERIFY( v.back() == 8 );
+
+ // vector::insert(const_iterator, size_type, const T&)
+ v.insert(v.begin(), 2, v.front());
+ v.insert(v.end(), 3, 99);
+ VERIFY( v.size() == 12 );
+
+ struct input_iterator
+ {
+ using iterator_category = std::input_iterator_tag;
+ using value_type = int;
+ using pointer = const int*;
+ using reference = int;
+ using difference_type = int;
+
+ constexpr input_iterator() : val(0) { }
+ constexpr input_iterator(int i) : val(i) { }
+
+ constexpr input_iterator& operator++() { --val; return *this; }
+ constexpr input_iterator operator++(int) { return {val--}; }
+
+ constexpr int operator*() const { return val; }
+ constexpr const int* operator->() const { return &val; }
+
+ constexpr bool operator==(const input_iterator&) const = default;
+
+ int val;
+ };
+
+ // vector::insert(const_iterator, Iter, Iter);
+ v.insert(v.begin() + 2, input_iterator(), input_iterator());
+ VERIFY( v.size() == 12 );
+ v.reserve(13);
+ auto n = v.capacity() - v.size();
+ v.insert(v.end() - 9, input_iterator(n), input_iterator()); // no reallocation
+ VERIFY( v.size() == (12 + n) );
+ short a[] = { 84, 85 };
+ v.insert(v.end() - 1, a, a + 2); // reallocation needed
+ VERIFY( v.size() == (12 + n + 2) );
+ v.resize(32);
+
+ // vector::insert(const_iterator, initializer_list<T>)
+ v.insert(v.begin(), {1,2,3});
+ VERIFY( v.size() == 35 );
+
+ v.rbegin()[0] = 999;
+ v.rbegin()[1] = 888;
+
+ // vector::erase(const_iterator)
+ v.erase(v.end() - 1);
+ VERIFY( v.size() == 34 );
+ VERIFY( v.back() == 888 );
+ v.erase(v.begin());
+ v.erase(v.begin() + 1);
+ v.erase(v.end() - 1);
+ VERIFY( v.size() == 31 );
+
+ // vector::erase(const_iterator, const_iterator)
+ v.erase(v.begin(), v.begin());
+ v.erase(v.end(), v.end());
+ v.erase(v.begin(), v.begin() + 1);
+ VERIFY( v.size() == 30 );
+ v.erase(v.begin() + 2, v.end() - 2);
+ VERIFY( v.size() == 4 );
+ v.erase(v.begin(), v.end());
+ VERIFY( v.empty() );
+ v.erase( v.begin(), v.begin() );
+ VERIFY( v.empty() );
+
+ v.insert(v.end(), 99);
+ for (std::size_t i = 0, c = v.capacity(); i <= c; ++i)
+ v.insert(v.end() - 1, v.front());
+ VERIFY( v.capacity() > v.size() );
+ v.insert(v.end(), 999);
+ for (std::size_t i = 0, c = v.capacity(); i <= c; ++i)
+ v.insert(v.begin(), v.front());
+
+ std::vector<int, Alloc<int>> va;
+ va.insert(va.begin(), 99);
+ va.insert(va.begin(), va.front());
+ VERIFY( va.size() == 2 );
+ va.erase(va.begin());
+
+ return true;
+}
+
+static_assert( test_insert_erase() );
+
+constexpr bool
+test_clear()
+{
+ std::vector<int> v0;
+ v0.clear();
+ VERIFY( v0.size() == 0 );
+ VERIFY( v0.capacity() == 0 );
+
+ std::vector<int> v{1, 10, 100};
+ v.clear();
+ VERIFY( v.size() == 0 );
+ VERIFY( v.capacity() == 3 );
+
+ std::vector<int, Alloc<int>> va;
+ va.clear();
+ va.push_back(1);
+ va.clear();
+ va.clear();
+
+ return true;
+}
+
+static_assert( test_clear() );
+
+constexpr bool
+test_erasure()
+{
+ const char* names[] = { "Vince", "Clarke", "Andy", "Bell" };
+ std::vector<const char*> e(std::begin(names), std::end(names));
+
+ auto n = std::erase(e, names[0]);
+ VERIFY( n == 1 );
+ VERIFY( e.size() == 3 );
+ n = std::erase_if(e, [](auto name) { return name[4] == '\0'; });
+ VERIFY( n == 2 );
+ VERIFY( e.size() == 1 );
+
+ return true;
+}
+
+static_assert( test_erasure() );
diff --git a/libstdc++-v3/testsuite/23_containers/vector/modifiers/swap/constexpr.cc b/libstdc++-v3/testsuite/23_containers/vector/modifiers/swap/constexpr.cc
new file mode 100644
index 0000000..4d06558
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/vector/modifiers/swap/constexpr.cc
@@ -0,0 +1,51 @@
+// { dg-options "-std=gnu++20" }
+// { dg-do compile { target c++20 } }
+// { dg-xfail-if "not supported" { debug-mode } }
+
+#include <vector>
+#include <utility>
+#include <testsuite_hooks.h>
+
+constexpr bool
+test_std_swap()
+{
+ std::vector<int> v1 = {1, 2, 3};
+ std::vector<int> v2 = {0, 1};
+
+ std::swap(v1, v2);
+
+ VERIFY(v1.size() == 2);
+ VERIFY(v1.at(0) == 0);
+ VERIFY(v1.at(1) == 1);
+
+ VERIFY(v2.size() == 3);
+ VERIFY(v2[0] == 1);
+ VERIFY(v2[1] == 2);
+ VERIFY(v2[2] == 3);
+
+ return true;
+}
+
+static_assert(test_std_swap());
+
+constexpr bool
+test_member_swap()
+{
+ std::vector<int> v1 = {1, 2, 3};
+ std::vector<int> v2 = {0, 1};
+
+ v1.swap(v2);
+
+ VERIFY(v1.size() == 2);
+ VERIFY(v1.at(0) == 0);
+ VERIFY(v1.at(1) == 1);
+
+ VERIFY(v2.size() == 3);
+ VERIFY(v2[0] == 1);
+ VERIFY(v2[1] == 2);
+ VERIFY(v2[2] == 3);
+
+ return true;
+}
+
+static_assert(test_member_swap());