[committed] libstdc++: Implement constexpr std::vector for C++20

Message ID 20211112004418.3125362-1-jwakely@redhat.com
State Committed
Commit 1ae8edf5f73ca5c3bf132cc52825dc1f709499dd
Headers
Series [committed] libstdc++: Implement constexpr std::vector for C++20 |

Commit Message

Jonathan Wakely Nov. 12, 2021, 12:44 a.m. UTC
  Tested x86_64-linux, committed to trunk.


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.
---
 libstdc++-v3/include/bits/alloc_traits.h      |   2 +
 libstdc++-v3/include/bits/allocator.h         |   1 +
 libstdc++-v3/include/bits/stl_algobase.h      |   1 +
 libstdc++-v3/include/bits/stl_bvector.h       | 251 ++++++++++++----
 libstdc++-v3/include/bits/stl_uninitialized.h | 158 ++++++----
 libstdc++-v3/include/bits/stl_vector.h        | 209 ++++++++++---
 libstdc++-v3/include/bits/vector.tcc          |  28 +-
 libstdc++-v3/include/std/vector               |   2 +
 .../23_containers/headers/vector/synopsis.cc  |  14 +
 .../vector/bool/capacity/29134.cc             |   5 -
 .../vector/bool/capacity/constexpr.cc         | 115 +++++++
 .../23_containers/vector/bool/cmp_c++20.cc    |  19 +-
 .../vector/bool/cons/constexpr.cc             | 280 ++++++++++++++++++
 .../vector/bool/element_access/constexpr.cc   | 102 +++++++
 .../vector/bool/modifiers/assign/constexpr.cc | 216 ++++++++++++++
 .../vector/bool/modifiers/constexpr.cc        | 248 ++++++++++++++++
 .../vector/bool/modifiers/insert/31370.cc     |   6 +-
 .../vector/bool/modifiers/swap/constexpr.cc   |  66 +++++
 .../vector/capacity/constexpr.cc              | 101 +++++++
 .../23_containers/vector/cmp_c++20.cc         |  49 +--
 .../23_containers/vector/cons/89164.cc        |  16 +-
 .../23_containers/vector/cons/89164_c++17.cc  |  39 +++
 .../23_containers/vector/cons/constexpr.cc    | 279 +++++++++++++++++
 .../vector/data_access/constexpr.cc           |  26 ++
 .../vector/element_access/constexpr.cc        |  91 ++++++
 .../vector/modifiers/assign/constexpr.cc      | 207 +++++++++++++
 .../vector/modifiers/constexpr.cc             | 226 ++++++++++++++
 .../vector/modifiers/swap/constexpr.cc        |  51 ++++
 28 files changed, 2606 insertions(+), 202 deletions(-)
 create mode 100644 libstdc++-v3/testsuite/23_containers/vector/bool/capacity/constexpr.cc
 create mode 100644 libstdc++-v3/testsuite/23_containers/vector/bool/cons/constexpr.cc
 create mode 100644 libstdc++-v3/testsuite/23_containers/vector/bool/element_access/constexpr.cc
 create mode 100644 libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/assign/constexpr.cc
 create mode 100644 libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/constexpr.cc
 create mode 100644 libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/swap/constexpr.cc
 create mode 100644 libstdc++-v3/testsuite/23_containers/vector/capacity/constexpr.cc
 create mode 100644 libstdc++-v3/testsuite/23_containers/vector/cons/89164_c++17.cc
 create mode 100644 libstdc++-v3/testsuite/23_containers/vector/cons/constexpr.cc
 create mode 100644 libstdc++-v3/testsuite/23_containers/vector/data_access/constexpr.cc
 create mode 100644 libstdc++-v3/testsuite/23_containers/vector/element_access/constexpr.cc
 create mode 100644 libstdc++-v3/testsuite/23_containers/vector/modifiers/assign/constexpr.cc
 create mode 100644 libstdc++-v3/testsuite/23_containers/vector/modifiers/constexpr.cc
 create mode 100644 libstdc++-v3/testsuite/23_containers/vector/modifiers/swap/constexpr.cc
  

Patch

diff --git a/libstdc++-v3/include/bits/alloc_traits.h b/libstdc++-v3/include/bits/alloc_traits.h
index 602a90d4d8a..a0a95f37f66 100644
--- a/libstdc++-v3/include/bits/alloc_traits.h
+++ b/libstdc++-v3/include/bits/alloc_traits.h
@@ -833,6 +833,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
    */
 
   template<typename _ForwardIterator, typename _Allocator>
+    _GLIBCXX20_CONSTEXPR
     void
     _Destroy(_ForwardIterator __first, _ForwardIterator __last,
 	     _Allocator& __alloc)
@@ -847,6 +848,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     }
 
   template<typename _ForwardIterator, typename _Tp>
+    _GLIBCXX20_CONSTEXPR
     inline void
     _Destroy(_ForwardIterator __first, _ForwardIterator __last,
 	     allocator<_Tp>&)
diff --git a/libstdc++-v3/include/bits/allocator.h b/libstdc++-v3/include/bits/allocator.h
index a6883c6758a..f83e6b87666 100644
--- a/libstdc++-v3/include/bits/allocator.h
+++ b/libstdc++-v3/include/bits/allocator.h
@@ -309,6 +309,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp>
     struct __shrink_to_fit_aux<_Tp, true>
     {
+      _GLIBCXX20_CONSTEXPR
       static bool
       _S_do_it(_Tp& __c) noexcept
       {
diff --git a/libstdc++-v3/include/bits/stl_algobase.h b/libstdc++-v3/include/bits/stl_algobase.h
index 0e0586836a6..f441165714b 100644
--- a/libstdc++-v3/include/bits/stl_algobase.h
+++ b/libstdc++-v3/include/bits/stl_algobase.h
@@ -956,6 +956,7 @@  _GLIBCXX_END_NAMESPACE_CONTAINER
 	      const _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*>&,
 	      const _VTp&);
 
+  _GLIBCXX20_CONSTEXPR
   void
   __fill_a1(_GLIBCXX_STD_C::_Bit_iterator, _GLIBCXX_STD_C::_Bit_iterator,
 	    const bool&);
diff --git a/libstdc++-v3/include/bits/stl_bvector.h b/libstdc++-v3/include/bits/stl_bvector.h
index 31d878427c2..381c47b6132 100644
--- a/libstdc++-v3/include/bits/stl_bvector.h
+++ b/libstdc++-v3/include/bits/stl_bvector.h
@@ -64,29 +64,38 @@ 
 namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
-_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 
   typedef unsigned long _Bit_type;
   enum { _S_word_bit = int(__CHAR_BIT__ * sizeof(_Bit_type)) };
 
+  __attribute__((__nonnull__))
+  _GLIBCXX20_CONSTEXPR
+  void
+  __fill_bvector_n(_Bit_type*, size_t, bool) _GLIBCXX_NOEXCEPT;
+
+_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
+
   struct _Bit_reference
   {
     _Bit_type * _M_p;
     _Bit_type _M_mask;
 
+    _GLIBCXX20_CONSTEXPR
     _Bit_reference(_Bit_type * __x, _Bit_type __y)
     : _M_p(__x), _M_mask(__y) { }
 
+    _GLIBCXX20_CONSTEXPR
     _Bit_reference() _GLIBCXX_NOEXCEPT : _M_p(0), _M_mask(0) { }
 
 #if __cplusplus >= 201103L
     _Bit_reference(const _Bit_reference&) = default;
 #endif
 
-    _GLIBCXX_NODISCARD
+    _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
     operator bool() const _GLIBCXX_NOEXCEPT
     { return !!(*_M_p & _M_mask); }
 
+    _GLIBCXX20_CONSTEXPR
     _Bit_reference&
     operator=(bool __x) _GLIBCXX_NOEXCEPT
     {
@@ -97,26 +106,29 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       return *this;
     }
 
+    _GLIBCXX20_CONSTEXPR
     _Bit_reference&
     operator=(const _Bit_reference& __x) _GLIBCXX_NOEXCEPT
     { return *this = bool(__x); }
 
-    _GLIBCXX_NODISCARD
+    _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
     bool
     operator==(const _Bit_reference& __x) const
     { return bool(*this) == bool(__x); }
 
-    _GLIBCXX_NODISCARD
+    _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
     bool
     operator<(const _Bit_reference& __x) const
     { return !bool(*this) && bool(__x); }
 
+    _GLIBCXX20_CONSTEXPR
     void
     flip() _GLIBCXX_NOEXCEPT
     { *_M_p ^= _M_mask; }
   };
 
 #if __cplusplus >= 201103L
+  _GLIBCXX20_CONSTEXPR
   inline void
   swap(_Bit_reference __x, _Bit_reference __y) noexcept
   {
@@ -125,6 +137,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
     __y = __tmp;
   }
 
+  _GLIBCXX20_CONSTEXPR
   inline void
   swap(_Bit_reference __x, bool& __y) noexcept
   {
@@ -133,6 +146,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
     __y = __tmp;
   }
 
+  _GLIBCXX20_CONSTEXPR
   inline void
   swap(bool& __x, _Bit_reference __y) noexcept
   {
@@ -148,9 +162,11 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
     _Bit_type * _M_p;
     unsigned int _M_offset;
 
+    _GLIBCXX20_CONSTEXPR
     _Bit_iterator_base(_Bit_type * __x, unsigned int __y)
     : _M_p(__x), _M_offset(__y) { }
 
+    _GLIBCXX20_CONSTEXPR
     void
     _M_bump_up()
     {
@@ -161,6 +177,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	}
     }
 
+    _GLIBCXX20_CONSTEXPR
     void
     _M_bump_down()
     {
@@ -171,6 +188,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	}
     }
 
+    _GLIBCXX20_CONSTEXPR
     void
     _M_incr(ptrdiff_t __i)
     {
@@ -230,7 +248,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
     { return !(__x < __y); }
 #endif // three-way comparison
 
-    friend ptrdiff_t
+    friend _GLIBCXX20_CONSTEXPR ptrdiff_t
     operator-(const _Bit_iterator_base& __x, const _Bit_iterator_base& __y)
     {
       return (int(_S_word_bit) * (__x._M_p - __y._M_p)
@@ -248,20 +266,24 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 #endif
     typedef _Bit_iterator   iterator;
 
+    _GLIBCXX20_CONSTEXPR
     _Bit_iterator() : _Bit_iterator_base(0, 0) { }
 
+    _GLIBCXX20_CONSTEXPR
     _Bit_iterator(_Bit_type * __x, unsigned int __y)
     : _Bit_iterator_base(__x, __y) { }
 
+    _GLIBCXX20_CONSTEXPR
     iterator
     _M_const_cast() const
     { return *this; }
 
-    _GLIBCXX_NODISCARD
+    _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
     reference
     operator*() const
     { return reference(_M_p, 1UL << _M_offset); }
 
+    _GLIBCXX20_CONSTEXPR
     iterator&
     operator++()
     {
@@ -269,6 +291,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       return *this;
     }
 
+    _GLIBCXX20_CONSTEXPR
     iterator
     operator++(int)
     {
@@ -277,6 +300,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       return __tmp;
     }
 
+    _GLIBCXX20_CONSTEXPR
     iterator&
     operator--()
     {
@@ -284,6 +308,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       return *this;
     }
 
+    _GLIBCXX20_CONSTEXPR
     iterator
     operator--(int)
     {
@@ -292,6 +317,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       return __tmp;
     }
 
+    _GLIBCXX20_CONSTEXPR
     iterator&
     operator+=(difference_type __i)
     {
@@ -299,6 +325,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       return *this;
     }
 
+    _GLIBCXX20_CONSTEXPR
     iterator&
     operator-=(difference_type __i)
     {
@@ -306,13 +333,13 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       return *this;
     }
 
-    _GLIBCXX_NODISCARD
+    _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
     reference
     operator[](difference_type __i) const
     { return *(*this + __i); }
 
     _GLIBCXX_NODISCARD
-    friend iterator
+    friend _GLIBCXX20_CONSTEXPR iterator
     operator+(const iterator& __x, difference_type __n)
     {
       iterator __tmp = __x;
@@ -321,12 +348,12 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
     }
 
     _GLIBCXX_NODISCARD
-    friend iterator
+    friend _GLIBCXX20_CONSTEXPR iterator
     operator+(difference_type __n, const iterator& __x)
     { return __x + __n; }
 
     _GLIBCXX_NODISCARD
-    friend iterator
+    friend _GLIBCXX20_CONSTEXPR iterator
     operator-(const iterator& __x, difference_type __n)
     {
       iterator __tmp = __x;
@@ -346,23 +373,28 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 #endif
     typedef _Bit_const_iterator  const_iterator;
 
+    _GLIBCXX20_CONSTEXPR
     _Bit_const_iterator() : _Bit_iterator_base(0, 0) { }
 
+    _GLIBCXX20_CONSTEXPR
     _Bit_const_iterator(_Bit_type * __x, unsigned int __y)
     : _Bit_iterator_base(__x, __y) { }
 
+    _GLIBCXX20_CONSTEXPR
     _Bit_const_iterator(const _Bit_iterator& __x)
     : _Bit_iterator_base(__x._M_p, __x._M_offset) { }
 
+    _GLIBCXX20_CONSTEXPR
     _Bit_iterator
     _M_const_cast() const
     { return _Bit_iterator(_M_p, _M_offset); }
 
-    _GLIBCXX_NODISCARD
+    _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
     const_reference
     operator*() const
     { return _Bit_reference(_M_p, 1UL << _M_offset); }
 
+    _GLIBCXX20_CONSTEXPR
     const_iterator&
     operator++()
     {
@@ -370,6 +402,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       return *this;
     }
 
+    _GLIBCXX20_CONSTEXPR
     const_iterator
     operator++(int)
     {
@@ -378,6 +411,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       return __tmp;
     }
 
+    _GLIBCXX20_CONSTEXPR
     const_iterator&
     operator--()
     {
@@ -385,6 +419,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       return *this;
     }
 
+    _GLIBCXX20_CONSTEXPR
     const_iterator
     operator--(int)
     {
@@ -393,6 +428,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       return __tmp;
     }
 
+    _GLIBCXX20_CONSTEXPR
     const_iterator&
     operator+=(difference_type __i)
     {
@@ -400,6 +436,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       return *this;
     }
 
+    _GLIBCXX20_CONSTEXPR
     const_iterator&
     operator-=(difference_type __i)
     {
@@ -407,13 +444,13 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       return *this;
     }
 
-    _GLIBCXX_NODISCARD
+    _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
     const_reference
     operator[](difference_type __i) const
     { return *(*this + __i); }
 
     _GLIBCXX_NODISCARD
-    friend const_iterator
+    friend _GLIBCXX20_CONSTEXPR const_iterator
     operator+(const const_iterator& __x, difference_type __n)
     {
       const_iterator __tmp = __x;
@@ -422,7 +459,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
     }
 
     _GLIBCXX_NODISCARD
-    friend const_iterator
+    friend _GLIBCXX20_CONSTEXPR const_iterator
     operator-(const const_iterator& __x, difference_type __n)
     {
       const_iterator __tmp = __x;
@@ -431,7 +468,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
     }
 
     _GLIBCXX_NODISCARD
-    friend const_iterator
+    friend _GLIBCXX20_CONSTEXPR const_iterator
     operator+(difference_type __n, const const_iterator& __x)
     { return __x + __n; }
   };
@@ -454,25 +491,30 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	struct {
 	  _Bit_type* _M_p;
 	  // Allow assignment from iterators (assume offset is zero):
+	  _GLIBCXX20_CONSTEXPR
 	  void operator=(_Bit_iterator __it) { _M_p = __it._M_p; }
 	} _M_start;
 #endif
 	_Bit_iterator	_M_finish;
 	_Bit_pointer	_M_end_of_storage;
 
+	_GLIBCXX20_CONSTEXPR
 	_Bvector_impl_data() _GLIBCXX_NOEXCEPT
 	: _M_start(), _M_finish(), _M_end_of_storage()
 	{ }
 
 #if __cplusplus >= 201103L
 	_Bvector_impl_data(const _Bvector_impl_data&) = default;
+
 	_Bvector_impl_data&
 	operator=(const _Bvector_impl_data&) = default;
 
+	_GLIBCXX20_CONSTEXPR
 	_Bvector_impl_data(_Bvector_impl_data&& __x) noexcept
 	: _Bvector_impl_data(__x)
 	{ __x._M_reset(); }
 
+	_GLIBCXX20_CONSTEXPR
 	void
 	_M_move_data(_Bvector_impl_data&& __x) noexcept
 	{
@@ -481,10 +523,12 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	}
 #endif
 
+	_GLIBCXX20_CONSTEXPR
 	void
 	_M_reset() _GLIBCXX_NOEXCEPT
 	{ *this = _Bvector_impl_data(); }
 
+	_GLIBCXX20_CONSTEXPR
 	void
 	_M_swap_data(_Bvector_impl_data& __x) _GLIBCXX_NOEXCEPT
 	{
@@ -497,11 +541,13 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       struct _Bvector_impl
 	: public _Bit_alloc_type, public _Bvector_impl_data
       {
+	_GLIBCXX20_CONSTEXPR
 	_Bvector_impl() _GLIBCXX_NOEXCEPT_IF(
 	  is_nothrow_default_constructible<_Bit_alloc_type>::value)
 	: _Bit_alloc_type()
 	{ }
 
+	_GLIBCXX20_CONSTEXPR
 	_Bvector_impl(const _Bit_alloc_type& __a) _GLIBCXX_NOEXCEPT
 	: _Bit_alloc_type(__a)
 	{ }
@@ -509,15 +555,18 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 #if __cplusplus >= 201103L
 	// Not defaulted, to enforce noexcept(true) even when
 	// !is_nothrow_move_constructible<_Bit_alloc_type>.
+	_GLIBCXX20_CONSTEXPR
 	_Bvector_impl(_Bvector_impl&& __x) noexcept
 	: _Bit_alloc_type(std::move(__x)), _Bvector_impl_data(std::move(__x))
 	{ }
 
+	_GLIBCXX20_CONSTEXPR
 	_Bvector_impl(_Bit_alloc_type&& __a, _Bvector_impl&& __x) noexcept
 	: _Bit_alloc_type(std::move(__a)), _Bvector_impl_data(std::move(__x))
 	{ }
 #endif
 
+	_GLIBCXX20_CONSTEXPR
 	_Bit_type*
 	_M_end_addr() const _GLIBCXX_NOEXCEPT
 	{
@@ -530,14 +579,17 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
     public:
       typedef _Alloc allocator_type;
 
+      _GLIBCXX20_CONSTEXPR
       _Bit_alloc_type&
       _M_get_Bit_allocator() _GLIBCXX_NOEXCEPT
       { return this->_M_impl; }
 
+      _GLIBCXX20_CONSTEXPR
       const _Bit_alloc_type&
       _M_get_Bit_allocator() const _GLIBCXX_NOEXCEPT
       { return this->_M_impl; }
 
+      _GLIBCXX20_CONSTEXPR
       allocator_type
       get_allocator() const _GLIBCXX_NOEXCEPT
       { return allocator_type(_M_get_Bit_allocator()); }
@@ -548,27 +600,43 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       _Bvector_base() { }
 #endif
 
+      _GLIBCXX20_CONSTEXPR
       _Bvector_base(const allocator_type& __a)
       : _M_impl(__a) { }
 
 #if __cplusplus >= 201103L
       _Bvector_base(_Bvector_base&&) = default;
 
+      _GLIBCXX20_CONSTEXPR
       _Bvector_base(_Bvector_base&& __x, const allocator_type& __a) noexcept
       : _M_impl(_Bit_alloc_type(__a), std::move(__x._M_impl))
       { }
 #endif
 
+      _GLIBCXX20_CONSTEXPR
       ~_Bvector_base()
       { this->_M_deallocate(); }
 
     protected:
       _Bvector_impl _M_impl;
 
+      _GLIBCXX20_CONSTEXPR
       _Bit_pointer
       _M_allocate(size_t __n)
-      { return _Bit_alloc_traits::allocate(_M_impl, _S_nword(__n)); }
+      {
+	_Bit_pointer __p = _Bit_alloc_traits::allocate(_M_impl, _S_nword(__n));
+#if __has_builtin(__builtin_is_constant_evaluated)
+	if (__builtin_is_constant_evaluated())
+	{
+	  __n = _S_nword(__n);
+	  for (size_t __i = 0; __i < __n; ++__i)
+	    __p[__i] = 0ul;
+	}
+#endif
+	return __p;
+      }
 
+      _GLIBCXX20_CONSTEXPR
       void
       _M_deallocate()
       {
@@ -583,11 +651,13 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       }
 
 #if __cplusplus >= 201103L
+      _GLIBCXX20_CONSTEXPR
       void
       _M_move_data(_Bvector_base&& __x) noexcept
       { _M_impl._M_move_data(std::move(__x._M_impl)); }
 #endif
 
+      _GLIBCXX_CONSTEXPR
       static size_t
       _S_nword(size_t __n)
       { return (__n + int(_S_word_bit) - 1) / int(_S_word_bit); }
@@ -637,6 +707,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       typedef std::reverse_iterator<iterator>		reverse_iterator;
       typedef _Alloc					allocator_type;
 
+      _GLIBCXX20_CONSTEXPR
       allocator_type
       get_allocator() const
       { return _Base::get_allocator(); }
@@ -654,16 +725,19 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       vector() { }
 #endif
 
+      _GLIBCXX20_CONSTEXPR
       explicit
       vector(const allocator_type& __a)
       : _Base(__a) { }
 
 #if __cplusplus >= 201103L
+      _GLIBCXX20_CONSTEXPR
       explicit
       vector(size_type __n, const allocator_type& __a = allocator_type())
       : vector(__n, false, __a)
       { }
 
+      _GLIBCXX20_CONSTEXPR
       vector(size_type __n, const bool& __value,
 	     const allocator_type& __a = allocator_type())
 #else
@@ -677,6 +751,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	_M_initialize_value(__value);
       }
 
+      _GLIBCXX20_CONSTEXPR
       vector(const vector& __x)
       : _Base(_Bit_alloc_traits::_S_select_on_copy(__x._M_get_Bit_allocator()))
       {
@@ -688,10 +763,12 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       vector(vector&&) = default;
 
     private:
+      _GLIBCXX20_CONSTEXPR
       vector(vector&& __x, const allocator_type& __a, true_type) noexcept
       : _Base(std::move(__x), __a)
       { }
 
+      _GLIBCXX20_CONSTEXPR
       vector(vector&& __x, const allocator_type& __a, false_type)
       : _Base(__a)
       {
@@ -706,12 +783,14 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       }
 
     public:
+      _GLIBCXX20_CONSTEXPR
       vector(vector&& __x, const __type_identity_t<allocator_type>& __a)
       noexcept(_Bit_alloc_traits::_S_always_equal())
       : vector(std::move(__x), __a,
 	       typename _Bit_alloc_traits::is_always_equal{})
       { }
 
+      _GLIBCXX20_CONSTEXPR
       vector(const vector& __x, const __type_identity_t<allocator_type>& __a)
       : _Base(__a)
       {
@@ -719,6 +798,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	_M_copy_aligned(__x.begin(), __x.end(), begin());
       }
 
+      _GLIBCXX20_CONSTEXPR
       vector(initializer_list<bool> __l,
 	     const allocator_type& __a = allocator_type())
       : _Base(__a)
@@ -731,6 +811,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 #if __cplusplus >= 201103L
       template<typename _InputIterator,
 	       typename = std::_RequireInputIter<_InputIterator>>
+	_GLIBCXX20_CONSTEXPR
 	vector(_InputIterator __first, _InputIterator __last,
 	       const allocator_type& __a = allocator_type())
 	: _Base(__a)
@@ -750,8 +831,10 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	}
 #endif
 
+      _GLIBCXX20_CONSTEXPR
       ~vector() _GLIBCXX_NOEXCEPT { }
 
+      _GLIBCXX20_CONSTEXPR
       vector&
       operator=(const vector& __x)
       {
@@ -783,6 +866,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       }
 
 #if __cplusplus >= 201103L
+      _GLIBCXX20_CONSTEXPR
       vector&
       operator=(vector&& __x) noexcept(_Bit_alloc_traits::_S_nothrow_move())
       {
@@ -808,6 +892,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	return *this;
       }
 
+      _GLIBCXX20_CONSTEXPR
       vector&
       operator=(initializer_list<bool> __l)
       {
@@ -820,6 +905,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       // versions: one that takes a count, and one that takes a range.
       // The range version is a member template, so we dispatch on whether
       // or not the type is an integer.
+      _GLIBCXX20_CONSTEXPR
       void
       assign(size_type __n, const bool& __x)
       { _M_fill_assign(__n, __x); }
@@ -827,6 +913,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 #if __cplusplus >= 201103L
       template<typename _InputIterator,
 	       typename = std::_RequireInputIter<_InputIterator>>
+	_GLIBCXX20_CONSTEXPR
 	void
 	assign(_InputIterator __first, _InputIterator __last)
 	{ _M_assign_aux(__first, __last, std::__iterator_category(__first)); }
@@ -842,79 +929,80 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 #endif
 
 #if __cplusplus >= 201103L
+      _GLIBCXX20_CONSTEXPR
       void
       assign(initializer_list<bool> __l)
       { _M_assign_aux(__l.begin(), __l.end(), random_access_iterator_tag()); }
 #endif
 
-      _GLIBCXX_NODISCARD
+      _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
       iterator
       begin() _GLIBCXX_NOEXCEPT
       { return iterator(this->_M_impl._M_start._M_p, 0); }
 
-      _GLIBCXX_NODISCARD
+      _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
       const_iterator
       begin() const _GLIBCXX_NOEXCEPT
       { return const_iterator(this->_M_impl._M_start._M_p, 0); }
 
-      _GLIBCXX_NODISCARD
+      _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
       iterator
       end() _GLIBCXX_NOEXCEPT
       { return this->_M_impl._M_finish; }
 
-      _GLIBCXX_NODISCARD
+      _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
       const_iterator
       end() const _GLIBCXX_NOEXCEPT
       { return this->_M_impl._M_finish; }
 
-      _GLIBCXX_NODISCARD
+      _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
       reverse_iterator
       rbegin() _GLIBCXX_NOEXCEPT
       { return reverse_iterator(end()); }
 
-      _GLIBCXX_NODISCARD
+      _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
       const_reverse_iterator
       rbegin() const _GLIBCXX_NOEXCEPT
       { return const_reverse_iterator(end()); }
 
-      _GLIBCXX_NODISCARD
+      _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
       reverse_iterator
       rend() _GLIBCXX_NOEXCEPT
       { return reverse_iterator(begin()); }
 
-      _GLIBCXX_NODISCARD
+      _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
       const_reverse_iterator
       rend() const _GLIBCXX_NOEXCEPT
       { return const_reverse_iterator(begin()); }
 
 #if __cplusplus >= 201103L
-      [[__nodiscard__]]
+      [[__nodiscard__]] _GLIBCXX20_CONSTEXPR
       const_iterator
       cbegin() const noexcept
       { return const_iterator(this->_M_impl._M_start._M_p, 0); }
 
-      [[__nodiscard__]]
+      [[__nodiscard__]] _GLIBCXX20_CONSTEXPR
       const_iterator
       cend() const noexcept
       { return this->_M_impl._M_finish; }
 
-      [[__nodiscard__]]
+      [[__nodiscard__]] _GLIBCXX20_CONSTEXPR
       const_reverse_iterator
       crbegin() const noexcept
       { return const_reverse_iterator(end()); }
 
-      [[__nodiscard__]]
+      [[__nodiscard__]] _GLIBCXX20_CONSTEXPR
       const_reverse_iterator
       crend() const noexcept
       { return const_reverse_iterator(begin()); }
 #endif
 
-      _GLIBCXX_NODISCARD
+      _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
       size_type
       size() const _GLIBCXX_NOEXCEPT
       { return size_type(end() - begin()); }
 
-      _GLIBCXX_NODISCARD
+      _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
       size_type
       max_size() const _GLIBCXX_NOEXCEPT
       {
@@ -927,27 +1015,29 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 		? __asize * int(_S_word_bit) : __isize);
       }
 
-      _GLIBCXX_NODISCARD
+      _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
       size_type
       capacity() const _GLIBCXX_NOEXCEPT
       { return size_type(const_iterator(this->_M_impl._M_end_addr(), 0)
 			 - begin()); }
 
-      _GLIBCXX_NODISCARD bool
+      _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
+      bool
       empty() const _GLIBCXX_NOEXCEPT
       { return begin() == end(); }
 
-      _GLIBCXX_NODISCARD
+      _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
       reference
       operator[](size_type __n)
       { return begin()[__n]; }
 
-      _GLIBCXX_NODISCARD
+      _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
       const_reference
       operator[](size_type __n) const
       { return begin()[__n]; }
 
     protected:
+      _GLIBCXX20_CONSTEXPR
       void
       _M_range_check(size_type __n) const
       {
@@ -959,14 +1049,23 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       }
 
     public:
+      _GLIBCXX20_CONSTEXPR
       reference
       at(size_type __n)
-      { _M_range_check(__n); return (*this)[__n]; }
+      {
+	_M_range_check(__n);
+	return (*this)[__n];
+      }
 
+      _GLIBCXX20_CONSTEXPR
       const_reference
       at(size_type __n) const
-      { _M_range_check(__n); return (*this)[__n]; }
+      {
+	_M_range_check(__n);
+	return (*this)[__n];
+      }
 
+      _GLIBCXX20_CONSTEXPR
       void
       reserve(size_type __n)
       {
@@ -976,26 +1075,27 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	  _M_reallocate(__n);
       }
 
-      _GLIBCXX_NODISCARD
+      _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
       reference
       front()
       { return *begin(); }
 
-      _GLIBCXX_NODISCARD
+      _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
       const_reference
       front() const
       { return *begin(); }
 
-      _GLIBCXX_NODISCARD
+      _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
       reference
       back()
       { return *(end() - 1); }
 
-      _GLIBCXX_NODISCARD
+      _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
       const_reference
       back() const
       { return *(end() - 1); }
 
+      _GLIBCXX20_CONSTEXPR
       void
       push_back(bool __x)
       {
@@ -1005,6 +1105,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	  _M_insert_aux(end(), __x);
       }
 
+      _GLIBCXX20_CONSTEXPR
       void
       swap(vector& __x) _GLIBCXX_NOEXCEPT
       {
@@ -1018,6 +1119,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       }
 
       // [23.2.5]/1, third-to-last entry in synopsis listing
+      _GLIBCXX20_CONSTEXPR
       static void
       swap(reference __x, reference __y) _GLIBCXX_NOEXCEPT
       {
@@ -1026,6 +1128,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	__y = __tmp;
       }
 
+      _GLIBCXX20_CONSTEXPR
       iterator
 #if __cplusplus >= 201103L
       insert(const_iterator __position, const bool& __x = bool())
@@ -1045,6 +1148,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 #if __cplusplus >= 201103L
       template<typename _InputIterator,
 	       typename = std::_RequireInputIter<_InputIterator>>
+	_GLIBCXX20_CONSTEXPR
 	iterator
 	insert(const_iterator __position,
 	       _InputIterator __first, _InputIterator __last)
@@ -1068,6 +1172,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 #endif
 
 #if __cplusplus >= 201103L
+      _GLIBCXX20_CONSTEXPR
       iterator
       insert(const_iterator __position, size_type __n, const bool& __x)
       {
@@ -1082,15 +1187,18 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 #endif
 
 #if __cplusplus >= 201103L
+      _GLIBCXX20_CONSTEXPR
       iterator
       insert(const_iterator __p, initializer_list<bool> __l)
       { return this->insert(__p, __l.begin(), __l.end()); }
 #endif
 
+      _GLIBCXX20_CONSTEXPR
       void
       pop_back()
       { --this->_M_impl._M_finish; }
 
+      _GLIBCXX20_CONSTEXPR
       iterator
 #if __cplusplus >= 201103L
       erase(const_iterator __position)
@@ -1099,6 +1207,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 #endif
       { return _M_erase(__position._M_const_cast()); }
 
+      _GLIBCXX20_CONSTEXPR
       iterator
 #if __cplusplus >= 201103L
       erase(const_iterator __first, const_iterator __last)
@@ -1107,6 +1216,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 #endif
       { return _M_erase(__first._M_const_cast(), __last._M_const_cast()); }
 
+      _GLIBCXX20_CONSTEXPR
       void
       resize(size_type __new_size, bool __x = bool())
       {
@@ -1117,11 +1227,13 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       }
 
 #if __cplusplus >= 201103L
+      _GLIBCXX20_CONSTEXPR
       void
       shrink_to_fit()
       { _M_shrink_to_fit(); }
 #endif
 
+      _GLIBCXX20_CONSTEXPR
       void
       flip() _GLIBCXX_NOEXCEPT
       {
@@ -1130,6 +1242,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	  *__p = ~*__p;
       }
 
+      _GLIBCXX20_CONSTEXPR
       void
       clear() _GLIBCXX_NOEXCEPT
       { _M_erase_at_end(begin()); }
@@ -1137,6 +1250,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 #if __cplusplus >= 201103L
       template<typename... _Args>
 #if __cplusplus > 201402L
+	_GLIBCXX20_CONSTEXPR
 	reference
 #else
 	void
@@ -1150,6 +1264,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	}
 
       template<typename... _Args>
+	_GLIBCXX20_CONSTEXPR
 	iterator
 	emplace(const_iterator __pos, _Args&&... __args)
 	{ return insert(__pos, bool(__args...)); }
@@ -1157,6 +1272,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 
     protected:
       // Precondition: __first._M_offset == 0 && __result._M_offset == 0.
+      _GLIBCXX20_CONSTEXPR
       iterator
       _M_copy_aligned(const_iterator __first, const_iterator __last,
 		      iterator __result)
@@ -1166,6 +1282,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 			 iterator(__q, 0));
       }
 
+      _GLIBCXX20_CONSTEXPR
       void
       _M_initialize(size_type __n)
       {
@@ -1179,19 +1296,20 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	  }
       }
 
+      _GLIBCXX20_CONSTEXPR
       void
-      _M_initialize_value(bool __x)
+      _M_initialize_value(bool __x) _GLIBCXX_NOEXCEPT
       {
 	if (_Bit_type* __p = this->_M_impl._M_start._M_p)
-	  __builtin_memset(__p, __x ? ~0 : 0,
-			   (this->_M_impl._M_end_addr() - __p)
-			   * sizeof(_Bit_type));
+	  __fill_bvector_n(__p, this->_M_impl._M_end_addr() - __p, __x);
       }
 
+      _GLIBCXX20_CONSTEXPR
       void
       _M_reallocate(size_type __n);
 
 #if __cplusplus >= 201103L
+      _GLIBCXX20_CONSTEXPR
       bool
       _M_shrink_to_fit();
 #endif
@@ -1216,6 +1334,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 #endif
 
       template<typename _InputIterator>
+	_GLIBCXX20_CONSTEXPR
 	void
 	_M_initialize_range(_InputIterator __first, _InputIterator __last,
 			    std::input_iterator_tag)
@@ -1225,6 +1344,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	}
 
       template<typename _ForwardIterator>
+	_GLIBCXX20_CONSTEXPR
 	void
 	_M_initialize_range(_ForwardIterator __first, _ForwardIterator __last,
 			    std::forward_iterator_tag)
@@ -1249,6 +1369,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	{ _M_assign_aux(__first, __last, std::__iterator_category(__first)); }
 #endif
 
+      _GLIBCXX20_CONSTEXPR
       void
       _M_fill_assign(size_t __n, bool __x)
       {
@@ -1265,6 +1386,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       }
 
       template<typename _InputIterator>
+	_GLIBCXX20_CONSTEXPR
 	void
 	_M_assign_aux(_InputIterator __first, _InputIterator __last,
 		      std::input_iterator_tag)
@@ -1279,6 +1401,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	}
 
       template<typename _ForwardIterator>
+	_GLIBCXX20_CONSTEXPR
 	void
 	_M_assign_aux(_ForwardIterator __first, _ForwardIterator __last,
 		      std::forward_iterator_tag)
@@ -1313,10 +1436,12 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 			  std::__iterator_category(__first)); }
 #endif
 
+      _GLIBCXX20_CONSTEXPR
       void
       _M_fill_insert(iterator __position, size_type __n, bool __x);
 
       template<typename _InputIterator>
+	_GLIBCXX20_CONSTEXPR
 	void
 	_M_insert_range(iterator __pos, _InputIterator __first,
 			_InputIterator __last, std::input_iterator_tag)
@@ -1329,13 +1454,16 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	}
 
       template<typename _ForwardIterator>
+	_GLIBCXX20_CONSTEXPR
 	void
 	_M_insert_range(iterator __position, _ForwardIterator __first,
 			_ForwardIterator __last, std::forward_iterator_tag);
 
+      _GLIBCXX20_CONSTEXPR
       void
       _M_insert_aux(iterator __position, bool __x);
 
+      _GLIBCXX20_CONSTEXPR
       size_type
       _M_check_len(size_type __n, const char* __s) const
       {
@@ -1346,13 +1474,16 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	return (__len < size() || __len > max_size()) ? max_size() : __len;
       }
 
+      _GLIBCXX20_CONSTEXPR
       void
       _M_erase_at_end(iterator __pos)
       { this->_M_impl._M_finish = __pos; }
 
+      _GLIBCXX20_CONSTEXPR
       iterator
       _M_erase(iterator __pos);
 
+      _GLIBCXX20_CONSTEXPR
       iterator
       _M_erase(iterator __first, iterator __last);
 
@@ -1371,12 +1502,12 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 
 _GLIBCXX_END_NAMESPACE_CONTAINER
 
+  // Fill a partial word.
+  _GLIBCXX20_CONSTEXPR
   inline void
-  __fill_bvector(_GLIBCXX_STD_C::_Bit_type * __v,
-		 unsigned int __first, unsigned int __last, bool __x)
+  __fill_bvector(_Bit_type* __v, unsigned int __first, unsigned int __last,
+		 bool __x) _GLIBCXX_NOEXCEPT
   {
-    using _GLIBCXX_STD_C::_Bit_type;
-    using _GLIBCXX_STD_C::_S_word_bit;
     const _Bit_type __fmask = ~0ul << __first;
     const _Bit_type __lmask = ~0ul >> (_S_word_bit - __last);
     const _Bit_type __mask = __fmask & __lmask;
@@ -1387,20 +1518,36 @@  _GLIBCXX_END_NAMESPACE_CONTAINER
       *__v &= ~__mask;
   }
 
+  // Fill N full words, as if using memset, but usable in constant expressions.
+  __attribute__((__nonnull__))
+  _GLIBCXX20_CONSTEXPR
+  inline void
+  __fill_bvector_n(_Bit_type* __p, size_t __n, bool __x) _GLIBCXX_NOEXCEPT
+  {
+#if __has_builtin(__builtin_is_constant_evaluated)
+    if (__builtin_is_constant_evaluated())
+    {
+      for (size_t __i = 0; __i < __n; ++__i)
+	__p[__i] = __x ? ~0ul : 0ul;
+      return;
+    }
+#endif
+    __builtin_memset(__p, __x ? ~0 : 0, __n * sizeof(_Bit_type));
+  }
+
+
+  _GLIBCXX20_CONSTEXPR
   inline void
   __fill_a1(_GLIBCXX_STD_C::_Bit_iterator __first,
 	    _GLIBCXX_STD_C::_Bit_iterator __last, const bool& __x)
   {
-    using _GLIBCXX_STD_C::_Bit_type;
-    using _GLIBCXX_STD_C::_S_word_bit;
     if (__first._M_p != __last._M_p)
       {
 	_Bit_type* __first_p = __first._M_p;
 	if (__first._M_offset != 0)
 	  __fill_bvector(__first_p++, __first._M_offset, _S_word_bit, __x);
 
-	__builtin_memset(__first_p, __x ? ~0 : 0,
-			 (__last._M_p - __first_p) * sizeof(_Bit_type));
+	__fill_bvector_n(__first_p, __last._M_p - __first_p, __x);
 
 	if (__last._M_offset != 0)
 	  __fill_bvector(__last._M_p, 0, __last._M_offset, __x);
diff --git a/libstdc++-v3/include/bits/stl_uninitialized.h b/libstdc++-v3/include/bits/stl_uninitialized.h
index 2fee1e17f00..673f6a07675 100644
--- a/libstdc++-v3/include/bits/stl_uninitialized.h
+++ b/libstdc++-v3/include/bits/stl_uninitialized.h
@@ -107,6 +107,26 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     __is_trivial(T) && __is_assignable(T&, U)
 #endif
 
+  template<typename _InputIterator, typename _ForwardIterator>
+    _GLIBCXX20_CONSTEXPR
+    _ForwardIterator
+    __do_uninit_copy(_InputIterator __first, _InputIterator __last,
+		     _ForwardIterator __result)
+    {
+      _ForwardIterator __cur = __result;
+      __try
+	{
+	  for (; __first != __last; ++__first, (void)++__cur)
+	    std::_Construct(std::__addressof(*__cur), *__first);
+	  return __cur;
+	}
+      __catch(...)
+	{
+	  std::_Destroy(__result, __cur);
+	  __throw_exception_again;
+	}
+    }
+
   template<bool _TrivialValueTypes>
     struct __uninitialized_copy
     {
@@ -114,20 +134,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
         static _ForwardIterator
         __uninit_copy(_InputIterator __first, _InputIterator __last,
 		      _ForwardIterator __result)
-        {
-	  _ForwardIterator __cur = __result;
-	  __try
-	    {
-	      for (; __first != __last; ++__first, (void)++__cur)
-		std::_Construct(std::__addressof(*__cur), *__first);
-	      return __cur;
-	    }
-	  __catch(...)
-	    {
-	      std::_Destroy(__result, __cur);
-	      __throw_exception_again;
-	    }
-	}
+	{ return std::__do_uninit_copy(__first, __last, __result); }
     };
 
   template<>
@@ -180,6 +187,24 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   /// @cond undocumented
 
+  template<typename _ForwardIterator, typename _Tp>
+    _GLIBCXX20_CONSTEXPR void
+    __do_uninit_fill(_ForwardIterator __first, _ForwardIterator __last,
+		     const _Tp& __x)
+    {
+      _ForwardIterator __cur = __first;
+      __try
+	{
+	  for (; __cur != __last; ++__cur)
+	    std::_Construct(std::__addressof(*__cur), __x);
+	}
+      __catch(...)
+	{
+	  std::_Destroy(__first, __cur);
+	  __throw_exception_again;
+	}
+    }
+
   template<bool _TrivialValueType>
     struct __uninitialized_fill
     {
@@ -187,19 +212,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
         static void
         __uninit_fill(_ForwardIterator __first, _ForwardIterator __last,
 		      const _Tp& __x)
-        {
-	  _ForwardIterator __cur = __first;
-	  __try
-	    {
-	      for (; __cur != __last; ++__cur)
-		std::_Construct(std::__addressof(*__cur), __x);
-	    }
-	  __catch(...)
-	    {
-	      std::_Destroy(__first, __cur);
-	      __throw_exception_again;
-	    }
-	}
+	{ std::__do_uninit_fill(__first, __last, __x); }
     };
 
   template<>
@@ -242,34 +255,40 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   /// @cond undocumented
 
+  template<typename _ForwardIterator, typename _Size, typename _Tp>
+    _GLIBCXX20_CONSTEXPR
+    _ForwardIterator
+    __do_uninit_fill_n(_ForwardIterator __first, _Size __n, const _Tp& __x)
+    {
+      _ForwardIterator __cur = __first;
+      __try
+	{
+	  for (; __n > 0; --__n, (void) ++__cur)
+	    std::_Construct(std::__addressof(*__cur), __x);
+	  return __cur;
+	}
+      __catch(...)
+	{
+	  std::_Destroy(__first, __cur);
+	  __throw_exception_again;
+	}
+    }
+
   template<bool _TrivialValueType>
     struct __uninitialized_fill_n
     {
       template<typename _ForwardIterator, typename _Size, typename _Tp>
-        static _ForwardIterator
+	static _ForwardIterator
         __uninit_fill_n(_ForwardIterator __first, _Size __n,
 			const _Tp& __x)
-        {
-	  _ForwardIterator __cur = __first;
-	  __try
-	    {
-	      for (; __n > 0; --__n, (void) ++__cur)
-		std::_Construct(std::__addressof(*__cur), __x);
-	      return __cur;
-	    }
-	  __catch(...)
-	    {
-	      std::_Destroy(__first, __cur);
-	      __throw_exception_again;
-	    }
-	}
+	{ return std::__do_uninit_fill_n(__first, __n, __x); }
     };
 
   template<>
     struct __uninitialized_fill_n<true>
     {
       template<typename _ForwardIterator, typename _Size, typename _Tp>
-        static _ForwardIterator
+	static _ForwardIterator
         __uninit_fill_n(_ForwardIterator __first, _Size __n,
 			const _Tp& __x)
         { return std::fill_n(__first, __n, __x); }
@@ -315,11 +334,12 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
   // Extensions: versions of uninitialized_copy, uninitialized_fill,
   //  and uninitialized_fill_n that take an allocator parameter.
   //  We dispatch back to the standard versions when we're given the
-  //  default allocator.  For nondefault allocators we do not use 
+  //  default allocator.  For nondefault allocators we do not use
   //  any of the POD optimizations.
 
   template<typename _InputIterator, typename _ForwardIterator,
 	   typename _Allocator>
+    _GLIBCXX20_CONSTEXPR
     _ForwardIterator
     __uninitialized_copy_a(_InputIterator __first, _InputIterator __last,
 			   _ForwardIterator __result, _Allocator& __alloc)
@@ -340,13 +360,21 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     }
 
   template<typename _InputIterator, typename _ForwardIterator, typename _Tp>
+    _GLIBCXX20_CONSTEXPR
     inline _ForwardIterator
     __uninitialized_copy_a(_InputIterator __first, _InputIterator __last,
 			   _ForwardIterator __result, allocator<_Tp>&)
-    { return std::uninitialized_copy(__first, __last, __result); }
+    {
+#ifdef __cpp_lib_is_constant_evaluated
+      if (std::is_constant_evaluated())
+	return std::__do_uninit_copy(__first, __last, __result);
+#endif
+      return std::uninitialized_copy(__first, __last, __result);
+    }
 
   template<typename _InputIterator, typename _ForwardIterator,
 	   typename _Allocator>
+    _GLIBCXX20_CONSTEXPR
     inline _ForwardIterator
     __uninitialized_move_a(_InputIterator __first, _InputIterator __last,
 			   _ForwardIterator __result, _Allocator& __alloc)
@@ -358,6 +386,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template<typename _InputIterator, typename _ForwardIterator,
 	   typename _Allocator>
+    _GLIBCXX20_CONSTEXPR
     inline _ForwardIterator
     __uninitialized_move_if_noexcept_a(_InputIterator __first,
 				       _InputIterator __last,
@@ -370,6 +399,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     }
 
   template<typename _ForwardIterator, typename _Tp, typename _Allocator>
+    _GLIBCXX20_CONSTEXPR
     void
     __uninitialized_fill_a(_ForwardIterator __first, _ForwardIterator __last,
 			   const _Tp& __x, _Allocator& __alloc)
@@ -389,15 +419,23 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     }
 
   template<typename _ForwardIterator, typename _Tp, typename _Tp2>
+    _GLIBCXX20_CONSTEXPR
     inline void
     __uninitialized_fill_a(_ForwardIterator __first, _ForwardIterator __last,
 			   const _Tp& __x, allocator<_Tp2>&)
-    { std::uninitialized_fill(__first, __last, __x); }
+    {
+#ifdef __cpp_lib_is_constant_evaluated
+      if (std::is_constant_evaluated())
+	return std::__do_uninit_fill(__first, __last, __x);
+#endif
+      std::uninitialized_fill(__first, __last, __x);
+    }
 
   template<typename _ForwardIterator, typename _Size, typename _Tp,
 	   typename _Allocator>
+     _GLIBCXX20_CONSTEXPR
     _ForwardIterator
-    __uninitialized_fill_n_a(_ForwardIterator __first, _Size __n, 
+    __uninitialized_fill_n_a(_ForwardIterator __first, _Size __n,
 			     const _Tp& __x, _Allocator& __alloc)
     {
       _ForwardIterator __cur = __first;
@@ -417,10 +455,17 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template<typename _ForwardIterator, typename _Size, typename _Tp,
 	   typename _Tp2>
+    _GLIBCXX20_CONSTEXPR
     inline _ForwardIterator
-    __uninitialized_fill_n_a(_ForwardIterator __first, _Size __n, 
+    __uninitialized_fill_n_a(_ForwardIterator __first, _Size __n,
 			     const _Tp& __x, allocator<_Tp2>&)
-    { return std::uninitialized_fill_n(__first, __n, __x); }
+    {
+#ifdef __cpp_lib_is_constant_evaluated
+      if (std::is_constant_evaluated())
+	return std::__do_uninit_fill_n(__first, __n, __x);
+#endif
+      return std::uninitialized_fill_n(__first, __n, __x);
+    }
 
 
   // Extensions: __uninitialized_copy_move, __uninitialized_move_copy,
@@ -483,7 +528,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	  __throw_exception_again;
 	}
     }
-  
+
   // __uninitialized_fill_move
   // Fills [result, mid) with x, and moves [first, last) into
   //  [mid, mid + (last - first)).
@@ -582,6 +627,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     struct __uninitialized_default_n_1
     {
       template<typename _ForwardIterator, typename _Size>
+	_GLIBCXX20_CONSTEXPR
         static _ForwardIterator
         __uninit_default_n(_ForwardIterator __first, _Size __n)
         {
@@ -604,6 +650,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     struct __uninitialized_default_n_1<true>
     {
       template<typename _ForwardIterator, typename _Size>
+	_GLIBCXX20_CONSTEXPR
         static _ForwardIterator
         __uninit_default_n(_ForwardIterator __first, _Size __n)
         {
@@ -639,6 +686,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
   // __uninitialized_default_n
   // Fills [first, first + n) with value-initialized value_types.
   template<typename _ForwardIterator, typename _Size>
+    _GLIBCXX20_CONSTEXPR
     inline _ForwardIterator
     __uninitialized_default_n(_ForwardIterator __first, _Size __n)
     {
@@ -689,8 +737,8 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
   // Fills [first, first + n) with value_types constructed by the allocator
   // alloc, with no arguments passed to the construct call.
   template<typename _ForwardIterator, typename _Size, typename _Allocator>
-    _ForwardIterator
-    __uninitialized_default_n_a(_ForwardIterator __first, _Size __n, 
+    _GLIBCXX20_CONSTEXPR _ForwardIterator
+    __uninitialized_default_n_a(_ForwardIterator __first, _Size __n,
 				_Allocator& __alloc)
     {
       _ForwardIterator __cur = __first;
@@ -711,8 +759,9 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
   // __uninitialized_default_n_a specialization for std::allocator,
   // which ignores the allocator and value-initializes the elements.
   template<typename _ForwardIterator, typename _Size, typename _Tp>
+    _GLIBCXX20_CONSTEXPR
     inline _ForwardIterator
-    __uninitialized_default_n_a(_ForwardIterator __first, _Size __n, 
+    __uninitialized_default_n_a(_ForwardIterator __first, _Size __n,
 				allocator<_Tp>&)
     { return std::__uninitialized_default_n(__first, __n); }
 
@@ -1022,6 +1071,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     : is_trivial<_Tp> { };
 
   template <typename _Tp, typename _Up>
+    _GLIBCXX20_CONSTEXPR
     inline __enable_if_t<std::__is_bitwise_relocatable<_Tp>::value, _Tp*>
     __relocate_a_1(_Tp* __first, _Tp* __last,
 		   _Tp* __result, allocator<_Up>&) noexcept
@@ -1034,6 +1084,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template <typename _InputIterator, typename _ForwardIterator,
 	    typename _Allocator>
+    _GLIBCXX20_CONSTEXPR
     inline _ForwardIterator
     __relocate_a_1(_InputIterator __first, _InputIterator __last,
 		   _ForwardIterator __result, _Allocator& __alloc)
@@ -1056,6 +1107,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template <typename _InputIterator, typename _ForwardIterator,
 	    typename _Allocator>
+    _GLIBCXX20_CONSTEXPR
     inline _ForwardIterator
     __relocate_a(_InputIterator __first, _InputIterator __last,
 		 _ForwardIterator __result, _Allocator& __alloc)
diff --git a/libstdc++-v3/include/bits/stl_vector.h b/libstdc++-v3/include/bits/stl_vector.h
index 2023581bc79..bd15b6bd8a8 100644
--- a/libstdc++-v3/include/bits/stl_vector.h
+++ b/libstdc++-v3/include/bits/stl_vector.h
@@ -94,17 +94,20 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	pointer _M_finish;
 	pointer _M_end_of_storage;
 
+	_GLIBCXX20_CONSTEXPR
 	_Vector_impl_data() _GLIBCXX_NOEXCEPT
 	: _M_start(), _M_finish(), _M_end_of_storage()
 	{ }
 
 #if __cplusplus >= 201103L
+	_GLIBCXX20_CONSTEXPR
 	_Vector_impl_data(_Vector_impl_data&& __x) noexcept
 	: _M_start(__x._M_start), _M_finish(__x._M_finish),
 	  _M_end_of_storage(__x._M_end_of_storage)
 	{ __x._M_start = __x._M_finish = __x._M_end_of_storage = pointer(); }
 #endif
 
+	_GLIBCXX20_CONSTEXPR
 	void
 	_M_copy_data(_Vector_impl_data const& __x) _GLIBCXX_NOEXCEPT
 	{
@@ -113,6 +116,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	  _M_end_of_storage = __x._M_end_of_storage;
 	}
 
+	_GLIBCXX20_CONSTEXPR
 	void
 	_M_swap_data(_Vector_impl_data& __x) _GLIBCXX_NOEXCEPT
 	{
@@ -128,11 +132,13 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       struct _Vector_impl
 	: public _Tp_alloc_type, public _Vector_impl_data
       {
+	_GLIBCXX20_CONSTEXPR
 	_Vector_impl() _GLIBCXX_NOEXCEPT_IF(
 	    is_nothrow_default_constructible<_Tp_alloc_type>::value)
 	: _Tp_alloc_type()
 	{ }
 
+	_GLIBCXX20_CONSTEXPR
 	_Vector_impl(_Tp_alloc_type const& __a) _GLIBCXX_NOEXCEPT
 	: _Tp_alloc_type(__a)
 	{ }
@@ -140,14 +146,17 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 #if __cplusplus >= 201103L
 	// Not defaulted, to enforce noexcept(true) even when
 	// !is_nothrow_move_constructible<_Tp_alloc_type>.
+	_GLIBCXX20_CONSTEXPR
 	_Vector_impl(_Vector_impl&& __x) noexcept
 	: _Tp_alloc_type(std::move(__x)), _Vector_impl_data(std::move(__x))
 	{ }
 
+	_GLIBCXX20_CONSTEXPR
 	_Vector_impl(_Tp_alloc_type&& __a) noexcept
 	: _Tp_alloc_type(std::move(__a))
 	{ }
 
+	_GLIBCXX20_CONSTEXPR
 	_Vector_impl(_Tp_alloc_type&& __a, _Vector_impl&& __rv) noexcept
 	: _Tp_alloc_type(std::move(__a)), _Vector_impl_data(std::move(__rv))
 	{ }
@@ -160,15 +169,17 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	    typedef typename __gnu_cxx::__alloc_traits<_Tp_alloc_type>
 	      ::size_type size_type;
 
-	    static void _S_shrink(_Vector_impl&, size_type) { }
-	    static void _S_on_dealloc(_Vector_impl&) { }
+	    static _GLIBCXX20_CONSTEXPR void
+	    _S_shrink(_Vector_impl&, size_type) { }
+	    static _GLIBCXX20_CONSTEXPR void
+	    _S_on_dealloc(_Vector_impl&) { }
 
 	    typedef _Vector_impl& _Reinit;
 
 	    struct _Grow
 	    {
-	      _Grow(_Vector_impl&, size_type) { }
-	      void _M_grew(size_type) { }
+	      _GLIBCXX20_CONSTEXPR _Grow(_Vector_impl&, size_type) { }
+	      _GLIBCXX20_CONSTEXPR void _M_grew(size_type) { }
 	    };
 	  };
 
@@ -181,22 +192,25 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 
 	    // Adjust ASan annotation for [_M_start, _M_end_of_storage) to
 	    // mark end of valid region as __curr instead of __prev.
-	    static void
+	    static _GLIBCXX20_CONSTEXPR void
 	    _S_adjust(_Vector_impl& __impl, pointer __prev, pointer __curr)
 	    {
+#if __has_builtin(__builtin_is_constant_evaluated)
+	      if (!__builtin_is_constant_evaluated())
+#endif
 	      __sanitizer_annotate_contiguous_container(__impl._M_start,
 		  __impl._M_end_of_storage, __prev, __curr);
 	    }
 
-	    static void
+	    static _GLIBCXX20_CONSTEXPR void
 	    _S_grow(_Vector_impl& __impl, size_type __n)
 	    { _S_adjust(__impl, __impl._M_finish, __impl._M_finish + __n); }
 
-	    static void
+	    static _GLIBCXX20_CONSTEXPR void
 	    _S_shrink(_Vector_impl& __impl, size_type __n)
 	    { _S_adjust(__impl, __impl._M_finish + __n, __impl._M_finish); }
 
-	    static void
+	    static _GLIBCXX20_CONSTEXPR void
 	    _S_on_dealloc(_Vector_impl& __impl)
 	    {
 	      if (__impl._M_start)
@@ -206,12 +220,14 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	    // Used on reallocation to tell ASan unused capacity is invalid.
 	    struct _Reinit
 	    {
-	      explicit _Reinit(_Vector_impl& __impl) : _M_impl(__impl)
+	      explicit _GLIBCXX20_CONSTEXPR
+	      _Reinit(_Vector_impl& __impl) : _M_impl(__impl)
 	      {
 		// Mark unused capacity as valid again before deallocating it.
 		_S_on_dealloc(_M_impl);
 	      }
 
+	      _GLIBCXX20_CONSTEXPR
 	      ~_Reinit()
 	      {
 		// Mark unused capacity as invalid after reallocation.
@@ -231,12 +247,15 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	    // Tell ASan when unused capacity is initialized to be valid.
 	    struct _Grow
 	    {
+	      _GLIBCXX20_CONSTEXPR
 	      _Grow(_Vector_impl& __impl, size_type __n)
 	      : _M_impl(__impl), _M_n(__n)
 	      { _S_grow(_M_impl, __n); }
 
+	      _GLIBCXX20_CONSTEXPR
 	      ~_Grow() { if (_M_n) _S_shrink(_M_impl, _M_n); }
 
+	      _GLIBCXX20_CONSTEXPR
 	      void _M_grew(size_type __n) { _M_n -= __n; }
 
 #if __cplusplus >= 201103L
@@ -272,14 +291,17 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
     public:
       typedef _Alloc allocator_type;
 
+      _GLIBCXX20_CONSTEXPR
       _Tp_alloc_type&
       _M_get_Tp_allocator() _GLIBCXX_NOEXCEPT
       { return this->_M_impl; }
 
+      _GLIBCXX20_CONSTEXPR
       const _Tp_alloc_type&
       _M_get_Tp_allocator() const _GLIBCXX_NOEXCEPT
       { return this->_M_impl; }
 
+      _GLIBCXX20_CONSTEXPR
       allocator_type
       get_allocator() const _GLIBCXX_NOEXCEPT
       { return allocator_type(_M_get_Tp_allocator()); }
@@ -290,16 +312,19 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       _Vector_base() { }
 #endif
 
+      _GLIBCXX20_CONSTEXPR
       _Vector_base(const allocator_type& __a) _GLIBCXX_NOEXCEPT
       : _M_impl(__a) { }
 
       // Kept for ABI compatibility.
 #if !_GLIBCXX_INLINE_VERSION
+      _GLIBCXX20_CONSTEXPR
       _Vector_base(size_t __n)
       : _M_impl()
       { _M_create_storage(__n); }
 #endif
 
+      _GLIBCXX20_CONSTEXPR
       _Vector_base(size_t __n, const allocator_type& __a)
       : _M_impl(__a)
       { _M_create_storage(__n); }
@@ -309,9 +334,11 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 
       // Kept for ABI compatibility.
 # if !_GLIBCXX_INLINE_VERSION
+      _GLIBCXX20_CONSTEXPR
       _Vector_base(_Tp_alloc_type&& __a) noexcept
       : _M_impl(std::move(__a)) { }
 
+      _GLIBCXX20_CONSTEXPR
       _Vector_base(_Vector_base&& __x, const allocator_type& __a)
       : _M_impl(__a)
       {
@@ -325,11 +352,13 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       }
 # endif
 
+      _GLIBCXX20_CONSTEXPR
       _Vector_base(const allocator_type& __a, _Vector_base&& __x)
       : _M_impl(_Tp_alloc_type(__a), std::move(__x._M_impl))
       { }
 #endif
 
+      _GLIBCXX20_CONSTEXPR
       ~_Vector_base() _GLIBCXX_NOEXCEPT
       {
 	_M_deallocate(_M_impl._M_start,
@@ -339,6 +368,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
     public:
       _Vector_impl _M_impl;
 
+      _GLIBCXX20_CONSTEXPR
       pointer
       _M_allocate(size_t __n)
       {
@@ -346,6 +376,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	return __n != 0 ? _Tr::allocate(_M_impl, __n) : pointer();
       }
 
+      _GLIBCXX20_CONSTEXPR
       void
       _M_deallocate(pointer __p, size_t __n)
       {
@@ -355,6 +386,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       }
 
     protected:
+      _GLIBCXX20_CONSTEXPR
       void
       _M_create_storage(size_t __n)
       {
@@ -443,25 +475,29 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       static constexpr bool
       _S_use_relocate()
       {
+#if __cplusplus >= 202002L && __has_builtin(__builtin_is_constant_evaluated)
+	if (__builtin_is_constant_evaluated())
+	  return false; // Cannot use memcpy in constant evaluation contexts.
+#endif
 	// Instantiating std::__relocate_a might cause an error outside the
 	// immediate context (in __relocate_object_a's noexcept-specifier),
 	// so only do it if we know the type can be move-inserted into *this.
 	return _S_nothrow_relocate(__is_move_insertable<_Tp_alloc_type>{});
       }
 
-      static pointer
+      static _GLIBCXX20_CONSTEXPR pointer
       _S_do_relocate(pointer __first, pointer __last, pointer __result,
 		     _Tp_alloc_type& __alloc, true_type) noexcept
       {
 	return std::__relocate_a(__first, __last, __result, __alloc);
       }
 
-      static pointer
+      static _GLIBCXX20_CONSTEXPR pointer
       _S_do_relocate(pointer, pointer, pointer __result,
 		     _Tp_alloc_type&, false_type) noexcept
       { return __result; }
 
-      static pointer
+      static _GLIBCXX20_CONSTEXPR pointer
       _S_relocate(pointer __first, pointer __last, pointer __result,
 		  _Tp_alloc_type& __alloc) noexcept
       {
@@ -494,6 +530,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  @param  __a  An allocator object.
        */
       explicit
+      _GLIBCXX20_CONSTEXPR
       vector(const allocator_type& __a) _GLIBCXX_NOEXCEPT
       : _Base(__a) { }
 
@@ -507,6 +544,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  constructed elements.
        */
       explicit
+      _GLIBCXX20_CONSTEXPR
       vector(size_type __n, const allocator_type& __a = allocator_type())
       : _Base(_S_check_init_len(__n, __a), __a)
       { _M_default_initialize(__n); }
@@ -519,6 +557,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *
        *  This constructor fills the %vector with @a __n copies of @a __value.
        */
+      _GLIBCXX20_CONSTEXPR
       vector(size_type __n, const value_type& __value,
 	     const allocator_type& __a = allocator_type())
       : _Base(_S_check_init_len(__n, __a), __a)
@@ -550,6 +589,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  The newly-created %vector uses a copy of the allocator object used
        *  by @a __x (unless the allocator traits dictate a different object).
        */
+      _GLIBCXX20_CONSTEXPR
       vector(const vector& __x)
       : _Base(__x.size(),
 	_Alloc_traits::_S_select_on_copy(__x._M_get_Tp_allocator()))
@@ -572,6 +612,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       vector(vector&&) noexcept = default;
 
       /// Copy constructor with alternative allocator
+      _GLIBCXX20_CONSTEXPR
       vector(const vector& __x, const __type_identity_t<allocator_type>& __a)
       : _Base(__x.size(), __a)
       {
@@ -582,10 +623,12 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       }
 
     private:
+      _GLIBCXX20_CONSTEXPR
       vector(vector&& __rv, const allocator_type& __m, true_type) noexcept
       : _Base(__m, std::move(__rv))
       { }
 
+      _GLIBCXX20_CONSTEXPR
       vector(vector&& __rv, const allocator_type& __m, false_type)
       : _Base(__m)
       {
@@ -604,6 +647,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 
     public:
       /// Move constructor with alternative allocator
+      _GLIBCXX20_CONSTEXPR
       vector(vector&& __rv, const __type_identity_t<allocator_type>& __m)
       noexcept( noexcept(
 	vector(std::declval<vector&&>(), std::declval<const allocator_type&>(),
@@ -622,6 +666,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  This will call the element type's copy constructor N times
        *  (where N is @a __l.size()) and do no memory reallocation.
        */
+      _GLIBCXX20_CONSTEXPR
       vector(initializer_list<value_type> __l,
 	     const allocator_type& __a = allocator_type())
       : _Base(__a)
@@ -650,6 +695,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 #if __cplusplus >= 201103L
       template<typename _InputIterator,
 	       typename = std::_RequireInputIter<_InputIterator>>
+	_GLIBCXX20_CONSTEXPR
 	vector(_InputIterator __first, _InputIterator __last,
 	       const allocator_type& __a = allocator_type())
 	: _Base(__a)
@@ -675,6 +721,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  not touched in any way.  Managing the pointer is the user's
        *  responsibility.
        */
+      _GLIBCXX20_CONSTEXPR
       ~vector() _GLIBCXX_NOEXCEPT
       {
 	std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
@@ -691,6 +738,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *
        *  Whether the allocator is copied depends on the allocator traits.
        */
+      _GLIBCXX20_CONSTEXPR
       vector&
       operator=(const vector& __x);
 
@@ -705,6 +753,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *
        *  Whether the allocator is moved depends on the allocator traits.
        */
+      _GLIBCXX20_CONSTEXPR
       vector&
       operator=(vector&& __x) noexcept(_Alloc_traits::_S_nothrow_move())
       {
@@ -726,6 +775,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  that the resulting %vector's size is the same as the number
        *  of elements assigned.
        */
+      _GLIBCXX20_CONSTEXPR
       vector&
       operator=(initializer_list<value_type> __l)
       {
@@ -745,6 +795,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  %vector and that the resulting %vector's size is the same as
        *  the number of elements assigned.
        */
+      _GLIBCXX20_CONSTEXPR
       void
       assign(size_type __n, const value_type& __val)
       { _M_fill_assign(__n, __val); }
@@ -764,6 +815,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 #if __cplusplus >= 201103L
       template<typename _InputIterator,
 	       typename = std::_RequireInputIter<_InputIterator>>
+	_GLIBCXX20_CONSTEXPR
 	void
 	assign(_InputIterator __first, _InputIterator __last)
 	{ _M_assign_dispatch(__first, __last, __false_type()); }
@@ -790,6 +842,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  that the resulting %vector's size is the same as the number
        *  of elements assigned.
        */
+      _GLIBCXX20_CONSTEXPR
       void
       assign(initializer_list<value_type> __l)
       {
@@ -807,7 +860,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  element in the %vector.  Iteration is done in ordinary
        *  element order.
        */
-      _GLIBCXX_NODISCARD
+      _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
       iterator
       begin() _GLIBCXX_NOEXCEPT
       { return iterator(this->_M_impl._M_start); }
@@ -817,7 +870,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  first element in the %vector.  Iteration is done in ordinary
        *  element order.
        */
-      _GLIBCXX_NODISCARD
+      _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
       const_iterator
       begin() const _GLIBCXX_NOEXCEPT
       { return const_iterator(this->_M_impl._M_start); }
@@ -827,7 +880,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  element in the %vector.  Iteration is done in ordinary
        *  element order.
        */
-      _GLIBCXX_NODISCARD
+      _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
       iterator
       end() _GLIBCXX_NOEXCEPT
       { return iterator(this->_M_impl._M_finish); }
@@ -837,7 +890,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  the last element in the %vector.  Iteration is done in
        *  ordinary element order.
        */
-      _GLIBCXX_NODISCARD
+      _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
       const_iterator
       end() const _GLIBCXX_NOEXCEPT
       { return const_iterator(this->_M_impl._M_finish); }
@@ -847,7 +900,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  last element in the %vector.  Iteration is done in reverse
        *  element order.
        */
-      _GLIBCXX_NODISCARD
+      _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
       reverse_iterator
       rbegin() _GLIBCXX_NOEXCEPT
       { return reverse_iterator(end()); }
@@ -857,7 +910,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  to the last element in the %vector.  Iteration is done in
        *  reverse element order.
        */
-      _GLIBCXX_NODISCARD
+      _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
       const_reverse_iterator
       rbegin() const _GLIBCXX_NOEXCEPT
       { return const_reverse_iterator(end()); }
@@ -867,7 +920,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  before the first element in the %vector.  Iteration is done
        *  in reverse element order.
        */
-      _GLIBCXX_NODISCARD
+      _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
       reverse_iterator
       rend() _GLIBCXX_NOEXCEPT
       { return reverse_iterator(begin()); }
@@ -877,7 +930,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  to one before the first element in the %vector.  Iteration
        *  is done in reverse element order.
        */
-      _GLIBCXX_NODISCARD
+      _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
       const_reverse_iterator
       rend() const _GLIBCXX_NOEXCEPT
       { return const_reverse_iterator(begin()); }
@@ -888,7 +941,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  first element in the %vector.  Iteration is done in ordinary
        *  element order.
        */
-      [[__nodiscard__]]
+      [[__nodiscard__]] _GLIBCXX20_CONSTEXPR
       const_iterator
       cbegin() const noexcept
       { return const_iterator(this->_M_impl._M_start); }
@@ -898,7 +951,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  the last element in the %vector.  Iteration is done in
        *  ordinary element order.
        */
-      [[__nodiscard__]]
+      [[__nodiscard__]] _GLIBCXX20_CONSTEXPR
       const_iterator
       cend() const noexcept
       { return const_iterator(this->_M_impl._M_finish); }
@@ -908,7 +961,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  to the last element in the %vector.  Iteration is done in
        *  reverse element order.
        */
-      [[__nodiscard__]]
+      [[__nodiscard__]] _GLIBCXX20_CONSTEXPR
       const_reverse_iterator
       crbegin() const noexcept
       { return const_reverse_iterator(end()); }
@@ -918,7 +971,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  to one before the first element in the %vector.  Iteration
        *  is done in reverse element order.
        */
-      [[__nodiscard__]]
+      [[__nodiscard__]] _GLIBCXX20_CONSTEXPR
       const_reverse_iterator
       crend() const noexcept
       { return const_reverse_iterator(begin()); }
@@ -926,13 +979,13 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 
       // [23.2.4.2] capacity
       /**  Returns the number of elements in the %vector.  */
-      _GLIBCXX_NODISCARD
+      _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
       size_type
       size() const _GLIBCXX_NOEXCEPT
       { return size_type(this->_M_impl._M_finish - this->_M_impl._M_start); }
 
       /**  Returns the size() of the largest possible %vector.  */
-      _GLIBCXX_NODISCARD
+      _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
       size_type
       max_size() const _GLIBCXX_NOEXCEPT
       { return _S_max_size(_M_get_Tp_allocator()); }
@@ -947,6 +1000,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  %vector's current size the %vector is truncated, otherwise
        *  default constructed elements are appended.
        */
+      _GLIBCXX20_CONSTEXPR
       void
       resize(size_type __new_size)
       {
@@ -967,6 +1021,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  the %vector is extended and new elements are populated with
        *  given data.
        */
+      _GLIBCXX20_CONSTEXPR
       void
       resize(size_type __new_size, const value_type& __x)
       {
@@ -987,6 +1042,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  the %vector is extended and new elements are populated with
        *  given data.
        */
+      _GLIBCXX20_CONSTEXPR
       void
       resize(size_type __new_size, value_type __x = value_type())
       {
@@ -999,6 +1055,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 
 #if __cplusplus >= 201103L
       /**  A non-binding request to reduce capacity() to size().  */
+      _GLIBCXX20_CONSTEXPR
       void
       shrink_to_fit()
       { _M_shrink_to_fit(); }
@@ -1008,7 +1065,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  Returns the total number of elements that the %vector can
        *  hold before needing to allocate more memory.
        */
-      _GLIBCXX_NODISCARD
+      _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
       size_type
       capacity() const _GLIBCXX_NOEXCEPT
       { return size_type(this->_M_impl._M_end_of_storage
@@ -1018,7 +1075,8 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  Returns true if the %vector is empty.  (Thus begin() would
        *  equal end().)
        */
-      _GLIBCXX_NODISCARD bool
+      _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
+      bool
       empty() const _GLIBCXX_NOEXCEPT
       { return begin() == end(); }
 
@@ -1039,6 +1097,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  %advance, and thus prevent a possible reallocation of memory
        *  and copying of %vector data.
        */
+      _GLIBCXX20_CONSTEXPR
       void
       reserve(size_type __n);
 
@@ -1054,7 +1113,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  out_of_range lookups are not defined. (For checked lookups
        *  see at().)
        */
-      _GLIBCXX_NODISCARD
+      _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
       reference
       operator[](size_type __n) _GLIBCXX_NOEXCEPT
       {
@@ -1073,7 +1132,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  out_of_range lookups are not defined. (For checked lookups
        *  see at().)
        */
-      _GLIBCXX_NODISCARD
+      _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
       const_reference
       operator[](size_type __n) const _GLIBCXX_NOEXCEPT
       {
@@ -1083,6 +1142,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 
     protected:
       /// Safety check used only from at().
+      _GLIBCXX20_CONSTEXPR
       void
       _M_range_check(size_type __n) const
       {
@@ -1105,6 +1165,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  is first checked that it is in the range of the vector.  The
        *  function throws out_of_range if the check fails.
        */
+      _GLIBCXX20_CONSTEXPR
       reference
       at(size_type __n)
       {
@@ -1123,6 +1184,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  is first checked that it is in the range of the vector.  The
        *  function throws out_of_range if the check fails.
        */
+      _GLIBCXX20_CONSTEXPR
       const_reference
       at(size_type __n) const
       {
@@ -1134,7 +1196,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  Returns a read/write reference to the data at the first
        *  element of the %vector.
        */
-      _GLIBCXX_NODISCARD
+      _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
       reference
       front() _GLIBCXX_NOEXCEPT
       {
@@ -1146,7 +1208,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  Returns a read-only (constant) reference to the data at the first
        *  element of the %vector.
        */
-      _GLIBCXX_NODISCARD
+      _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
       const_reference
       front() const _GLIBCXX_NOEXCEPT
       {
@@ -1158,7 +1220,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  Returns a read/write reference to the data at the last
        *  element of the %vector.
        */
-      _GLIBCXX_NODISCARD
+      _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
       reference
       back() _GLIBCXX_NOEXCEPT
       {
@@ -1170,7 +1232,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  Returns a read-only (constant) reference to the data at the
        *  last element of the %vector.
        */
-      _GLIBCXX_NODISCARD
+      _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
       const_reference
       back() const _GLIBCXX_NOEXCEPT
       {
@@ -1185,12 +1247,12 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *   Returns a pointer such that [data(), data() + size()) is a valid
        *   range.  For a non-empty %vector, data() == &front().
        */
-      _GLIBCXX_NODISCARD
+      _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
       _Tp*
       data() _GLIBCXX_NOEXCEPT
       { return _M_data_ptr(this->_M_impl._M_start); }
 
-      _GLIBCXX_NODISCARD
+      _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
       const _Tp*
       data() const _GLIBCXX_NOEXCEPT
       { return _M_data_ptr(this->_M_impl._M_start); }
@@ -1206,6 +1268,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  done in constant time if the %vector has preallocated space
        *  available.
        */
+      _GLIBCXX20_CONSTEXPR
       void
       push_back(const value_type& __x)
       {
@@ -1222,12 +1285,14 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       }
 
 #if __cplusplus >= 201103L
+      _GLIBCXX20_CONSTEXPR
       void
       push_back(value_type&& __x)
       { emplace_back(std::move(__x)); }
 
       template<typename... _Args>
 #if __cplusplus > 201402L
+	_GLIBCXX20_CONSTEXPR
 	reference
 #else
 	void
@@ -1244,6 +1309,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  data is needed, it should be retrieved before pop_back() is
        *  called.
        */
+      _GLIBCXX20_CONSTEXPR
       void
       pop_back() _GLIBCXX_NOEXCEPT
       {
@@ -1267,6 +1333,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  std::list.
        */
       template<typename... _Args>
+	_GLIBCXX20_CONSTEXPR
 	iterator
 	emplace(const_iterator __position, _Args&&... __args)
 	{ return _M_emplace_aux(__position, std::forward<_Args>(__args)...); }
@@ -1282,6 +1349,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  could be expensive for a %vector and if it is frequently
        *  used the user should consider using std::list.
        */
+      _GLIBCXX20_CONSTEXPR
       iterator
       insert(const_iterator __position, const value_type& __x);
 #else
@@ -1312,6 +1380,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  could be expensive for a %vector and if it is frequently
        *  used the user should consider using std::list.
        */
+      _GLIBCXX20_CONSTEXPR
       iterator
       insert(const_iterator __position, value_type&& __x)
       { return _M_insert_rval(__position, std::move(__x)); }
@@ -1329,6 +1398,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  %vector and if it is frequently used the user should
        *  consider using std::list.
        */
+      _GLIBCXX20_CONSTEXPR
       iterator
       insert(const_iterator __position, initializer_list<value_type> __l)
       {
@@ -1354,6 +1424,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  %vector and if it is frequently used the user should
        *  consider using std::list.
        */
+      _GLIBCXX20_CONSTEXPR
       iterator
       insert(const_iterator __position, size_type __n, const value_type& __x)
       {
@@ -1398,6 +1469,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        */
       template<typename _InputIterator,
 	       typename = std::_RequireInputIter<_InputIterator>>
+	_GLIBCXX20_CONSTEXPR
 	iterator
 	insert(const_iterator __position, _InputIterator __first,
 	       _InputIterator __last)
@@ -1448,6 +1520,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  the pointed-to memory is not touched in any way.  Managing
        *  the pointer is the user's responsibility.
        */
+      _GLIBCXX20_CONSTEXPR
       iterator
 #if __cplusplus >= 201103L
       erase(const_iterator __position)
@@ -1475,6 +1548,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  pointers, the pointed-to memory is not touched in any way.
        *  Managing the pointer is the user's responsibility.
        */
+      _GLIBCXX20_CONSTEXPR
       iterator
 #if __cplusplus >= 201103L
       erase(const_iterator __first, const_iterator __last)
@@ -1499,6 +1573,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *
        *  Whether the allocators are swapped depends on the allocator traits.
        */
+      _GLIBCXX20_CONSTEXPR
       void
       swap(vector& __x) _GLIBCXX_NOEXCEPT
       {
@@ -1517,6 +1592,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  pointed-to memory is not touched in any way.  Managing the pointer is
        *  the user's responsibility.
        */
+      _GLIBCXX20_CONSTEXPR
       void
       clear() _GLIBCXX_NOEXCEPT
       { _M_erase_at_end(this->_M_impl._M_start); }
@@ -1527,6 +1603,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  obtain @a n bytes of memory, and then copies [first,last) into it.
        */
       template<typename _ForwardIterator>
+	_GLIBCXX20_CONSTEXPR
 	pointer
 	_M_allocate_and_copy(size_type __n,
 			     _ForwardIterator __first, _ForwardIterator __last)
@@ -1577,6 +1654,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 
       // Called by the second initialize_dispatch above
       template<typename _InputIterator>
+	_GLIBCXX20_CONSTEXPR
 	void
 	_M_range_initialize(_InputIterator __first, _InputIterator __last,
 			    std::input_iterator_tag)
@@ -1596,6 +1674,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 
       // Called by the second initialize_dispatch above
       template<typename _ForwardIterator>
+	_GLIBCXX20_CONSTEXPR
 	void
 	_M_range_initialize(_ForwardIterator __first, _ForwardIterator __last,
 			    std::forward_iterator_tag)
@@ -1612,6 +1691,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 
       // Called by the first initialize_dispatch above and by the
       // vector(n,value,a) constructor.
+      _GLIBCXX20_CONSTEXPR
       void
       _M_fill_initialize(size_type __n, const value_type& __value)
       {
@@ -1622,6 +1702,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 
 #if __cplusplus >= 201103L
       // Called by the vector(n) constructor.
+      _GLIBCXX20_CONSTEXPR
       void
       _M_default_initialize(size_type __n)
       {
@@ -1639,12 +1720,14 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       // _GLIBCXX_RESOLVE_LIB_DEFECTS
       // 438. Ambiguity in the "do the right thing" clause
       template<typename _Integer>
+	_GLIBCXX20_CONSTEXPR
 	void
 	_M_assign_dispatch(_Integer __n, _Integer __val, __true_type)
 	{ _M_fill_assign(__n, __val); }
 
       // Called by the range assign to implement [23.1.1]/9
       template<typename _InputIterator>
+	_GLIBCXX20_CONSTEXPR
 	void
 	_M_assign_dispatch(_InputIterator __first, _InputIterator __last,
 			   __false_type)
@@ -1652,18 +1735,21 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 
       // Called by the second assign_dispatch above
       template<typename _InputIterator>
+	_GLIBCXX20_CONSTEXPR
 	void
 	_M_assign_aux(_InputIterator __first, _InputIterator __last,
 		      std::input_iterator_tag);
 
       // Called by the second assign_dispatch above
       template<typename _ForwardIterator>
+	_GLIBCXX20_CONSTEXPR
 	void
 	_M_assign_aux(_ForwardIterator __first, _ForwardIterator __last,
 		      std::forward_iterator_tag);
 
       // Called by assign(n,t), and the range assign when it turns out
       // to be the same thing.
+      _GLIBCXX20_CONSTEXPR
       void
       _M_fill_assign(size_type __n, const value_type& __val);
 
@@ -1674,6 +1760,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       // _GLIBCXX_RESOLVE_LIB_DEFECTS
       // 438. Ambiguity in the "do the right thing" clause
       template<typename _Integer>
+	_GLIBCXX20_CONSTEXPR
 	void
 	_M_insert_dispatch(iterator __pos, _Integer __n, _Integer __val,
 			   __true_type)
@@ -1681,6 +1768,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 
       // Called by the range insert to implement [23.1.1]/9
       template<typename _InputIterator>
+	_GLIBCXX20_CONSTEXPR
 	void
 	_M_insert_dispatch(iterator __pos, _InputIterator __first,
 			   _InputIterator __last, __false_type)
@@ -1691,26 +1779,31 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 
       // Called by the second insert_dispatch above
       template<typename _InputIterator>
+	_GLIBCXX20_CONSTEXPR
 	void
 	_M_range_insert(iterator __pos, _InputIterator __first,
 			_InputIterator __last, std::input_iterator_tag);
 
       // Called by the second insert_dispatch above
       template<typename _ForwardIterator>
+	_GLIBCXX20_CONSTEXPR
 	void
 	_M_range_insert(iterator __pos, _ForwardIterator __first,
 			_ForwardIterator __last, std::forward_iterator_tag);
 
       // Called by insert(p,n,x), and the range insert when it turns out to be
       // the same thing.
+      _GLIBCXX20_CONSTEXPR
       void
       _M_fill_insert(iterator __pos, size_type __n, const value_type& __x);
 
 #if __cplusplus >= 201103L
       // Called by resize(n).
+      _GLIBCXX20_CONSTEXPR
       void
       _M_default_append(size_type __n);
 
+      _GLIBCXX20_CONSTEXPR
       bool
       _M_shrink_to_fit();
 #endif
@@ -1728,53 +1821,69 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       struct _Temporary_value
       {
 	template<typename... _Args>
-	  explicit
+	  _GLIBCXX20_CONSTEXPR explicit
 	  _Temporary_value(vector* __vec, _Args&&... __args) : _M_this(__vec)
 	  {
 	    _Alloc_traits::construct(_M_this->_M_impl, _M_ptr(),
 				     std::forward<_Args>(__args)...);
 	  }
 
+	_GLIBCXX20_CONSTEXPR
 	~_Temporary_value()
 	{ _Alloc_traits::destroy(_M_this->_M_impl, _M_ptr()); }
 
-	value_type&
-	_M_val() { return *_M_ptr(); }
+	_GLIBCXX20_CONSTEXPR value_type&
+	_M_val() noexcept { return _M_storage._M_val; }
 
       private:
-	_Tp*
-	_M_ptr() { return reinterpret_cast<_Tp*>(&__buf); }
+	_GLIBCXX20_CONSTEXPR _Tp*
+	_M_ptr() noexcept { return std::__addressof(_M_storage._M_val); }
 
-	vector* _M_this;
-	typename aligned_storage<sizeof(_Tp), alignof(_Tp)>::type __buf;
+	union _Storage
+	{
+	  constexpr _Storage() : _M_byte() { }
+	  _GLIBCXX20_CONSTEXPR ~_Storage() { }
+	  _Storage& operator=(const _Storage&) = delete;
+	  unsigned char _M_byte;
+	  _Tp _M_val;
+	};
+
+	vector*  _M_this;
+	_Storage _M_storage;
       };
 
       // Called by insert(p,x) and other functions when insertion needs to
       // reallocate or move existing elements. _Arg is either _Tp& or _Tp.
       template<typename _Arg>
+	_GLIBCXX20_CONSTEXPR
 	void
 	_M_insert_aux(iterator __position, _Arg&& __arg);
 
       template<typename... _Args>
+	_GLIBCXX20_CONSTEXPR
 	void
 	_M_realloc_insert(iterator __position, _Args&&... __args);
 
       // Either move-construct at the end, or forward to _M_insert_aux.
+      _GLIBCXX20_CONSTEXPR
       iterator
       _M_insert_rval(const_iterator __position, value_type&& __v);
 
       // Try to emplace at the end, otherwise forward to _M_insert_aux.
       template<typename... _Args>
+	_GLIBCXX20_CONSTEXPR
 	iterator
 	_M_emplace_aux(const_iterator __position, _Args&&... __args);
 
       // Emplacing an rvalue of the correct type can use _M_insert_rval.
+      _GLIBCXX20_CONSTEXPR
       iterator
       _M_emplace_aux(const_iterator __position, value_type&& __v)
       { return _M_insert_rval(__position, std::move(__v)); }
 #endif
 
       // Called by _M_fill_insert, _M_insert_aux etc.
+      _GLIBCXX20_CONSTEXPR
       size_type
       _M_check_len(size_type __n, const char* __s) const
       {
@@ -1786,7 +1895,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       }
 
       // Called by constructors to check initial size.
-      static size_type
+      static _GLIBCXX20_CONSTEXPR size_type
       _S_check_init_len(size_type __n, const allocator_type& __a)
       {
 	if (__n > _S_max_size(_Tp_alloc_type(__a)))
@@ -1795,7 +1904,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	return __n;
       }
 
-      static size_type
+      static _GLIBCXX20_CONSTEXPR size_type
       _S_max_size(const _Tp_alloc_type& __a) _GLIBCXX_NOEXCEPT
       {
 	// std::distance(begin(), end()) cannot be greater than PTRDIFF_MAX,
@@ -1811,6 +1920,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 
       // Called by erase(q1,q2), clear(), resize(), _M_fill_assign,
       // _M_assign_aux.
+      _GLIBCXX20_CONSTEXPR
       void
       _M_erase_at_end(pointer __pos) _GLIBCXX_NOEXCEPT
       {
@@ -1823,9 +1933,11 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	  }
       }
 
+      _GLIBCXX20_CONSTEXPR
       iterator
       _M_erase(iterator __position);
 
+      _GLIBCXX20_CONSTEXPR
       iterator
       _M_erase(iterator __first, iterator __last);
 
@@ -1834,6 +1946,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       // Constant-time move assignment when source object's memory can be
       // moved, either because the source's allocator will move too
       // or because the allocators are equal.
+      _GLIBCXX20_CONSTEXPR
       void
       _M_move_assign(vector&& __x, true_type) noexcept
       {
@@ -1845,6 +1958,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 
       // Do move assignment when it might not be possible to move source
       // object's memory, resulting in a linear-time operation.
+      _GLIBCXX20_CONSTEXPR
       void
       _M_move_assign(vector&& __x, false_type)
       {
@@ -1863,12 +1977,14 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 #endif
 
       template<typename _Up>
+	_GLIBCXX20_CONSTEXPR
 	_Up*
 	_M_data_ptr(_Up* __ptr) const _GLIBCXX_NOEXCEPT
 	{ return __ptr; }
 
 #if __cplusplus >= 201103L
       template<typename _Ptr>
+	_GLIBCXX20_CONSTEXPR
 	typename std::pointer_traits<_Ptr>::element_type*
 	_M_data_ptr(_Ptr __ptr) const
 	{ return empty() ? nullptr : std::__to_address(__ptr); }
@@ -1911,6 +2027,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
    *  and if corresponding elements compare equal.
   */
   template<typename _Tp, typename _Alloc>
+    _GLIBCXX20_CONSTEXPR
     inline bool
     operator==(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y)
     { return (__x.size() == __y.size()
@@ -1929,6 +2046,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
    *  `<` and `>=` etc.
   */
   template<typename _Tp, typename _Alloc>
+    _GLIBCXX20_CONSTEXPR
     inline __detail::__synth3way_t<_Tp>
     operator<=>(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y)
     {
@@ -1981,6 +2099,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 
   /// See std::vector::swap().
   template<typename _Tp, typename _Alloc>
+    _GLIBCXX20_CONSTEXPR
     inline void
     swap(vector<_Tp, _Alloc>& __x, vector<_Tp, _Alloc>& __y)
     _GLIBCXX_NOEXCEPT_IF(noexcept(__x.swap(__y)))
diff --git a/libstdc++-v3/include/bits/vector.tcc b/libstdc++-v3/include/bits/vector.tcc
index 16366e03c86..7e3115cb7a6 100644
--- a/libstdc++-v3/include/bits/vector.tcc
+++ b/libstdc++-v3/include/bits/vector.tcc
@@ -62,6 +62,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 
   template<typename _Tp, typename _Alloc>
+    _GLIBCXX20_CONSTEXPR
     void
     vector<_Tp, _Alloc>::
     reserve(size_type __n)
@@ -102,6 +103,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
   template<typename _Tp, typename _Alloc>
     template<typename... _Args>
 #if __cplusplus > 201402L
+      _GLIBCXX20_CONSTEXPR
       typename vector<_Tp, _Alloc>::reference
 #else
       void
@@ -126,6 +128,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 #endif
 
   template<typename _Tp, typename _Alloc>
+    _GLIBCXX20_CONSTEXPR
     typename vector<_Tp, _Alloc>::iterator
     vector<_Tp, _Alloc>::
 #if __cplusplus >= 201103L
@@ -167,6 +170,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
     }
 
   template<typename _Tp, typename _Alloc>
+    _GLIBCXX20_CONSTEXPR
     typename vector<_Tp, _Alloc>::iterator
     vector<_Tp, _Alloc>::
     _M_erase(iterator __position)
@@ -180,6 +184,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
     }
 
   template<typename _Tp, typename _Alloc>
+    _GLIBCXX20_CONSTEXPR
     typename vector<_Tp, _Alloc>::iterator
     vector<_Tp, _Alloc>::
     _M_erase(iterator __first, iterator __last)
@@ -194,6 +199,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
     }
 
   template<typename _Tp, typename _Alloc>
+    _GLIBCXX20_CONSTEXPR
     vector<_Tp, _Alloc>&
     vector<_Tp, _Alloc>::
     operator=(const vector<_Tp, _Alloc>& __x)
@@ -253,6 +259,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
     }
 
   template<typename _Tp, typename _Alloc>
+    _GLIBCXX20_CONSTEXPR
     void
     vector<_Tp, _Alloc>::
     _M_fill_assign(size_t __n, const value_type& __val)
@@ -278,6 +285,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 
   template<typename _Tp, typename _Alloc>
     template<typename _InputIterator>
+      _GLIBCXX20_CONSTEXPR
       void
       vector<_Tp, _Alloc>::
       _M_assign_aux(_InputIterator __first, _InputIterator __last,
@@ -296,6 +304,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 
   template<typename _Tp, typename _Alloc>
     template<typename _ForwardIterator>
+      _GLIBCXX20_CONSTEXPR
       void
       vector<_Tp, _Alloc>::
       _M_assign_aux(_ForwardIterator __first, _ForwardIterator __last,
@@ -336,6 +345,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 
 #if __cplusplus >= 201103L
   template<typename _Tp, typename _Alloc>
+    _GLIBCXX20_CONSTEXPR
     auto
     vector<_Tp, _Alloc>::
     _M_insert_rval(const_iterator __position, value_type&& __v) -> iterator
@@ -360,6 +370,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 
   template<typename _Tp, typename _Alloc>
     template<typename... _Args>
+      _GLIBCXX20_CONSTEXPR
       auto
       vector<_Tp, _Alloc>::
       _M_emplace_aux(const_iterator __position, _Args&&... __args)
@@ -391,6 +402,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 
   template<typename _Tp, typename _Alloc>
     template<typename _Arg>
+      _GLIBCXX20_CONSTEXPR
       void
       vector<_Tp, _Alloc>::
       _M_insert_aux(iterator __position, _Arg&& __arg)
@@ -422,6 +434,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 #if __cplusplus >= 201103L
   template<typename _Tp, typename _Alloc>
     template<typename... _Args>
+      _GLIBCXX20_CONSTEXPR
       void
       vector<_Tp, _Alloc>::
       _M_realloc_insert(iterator __position, _Args&&... __args)
@@ -505,6 +518,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
     }
 
   template<typename _Tp, typename _Alloc>
+    _GLIBCXX20_CONSTEXPR
     void
     vector<_Tp, _Alloc>::
     _M_fill_insert(iterator __position, size_type __n, const value_type& __x)
@@ -607,6 +621,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 
 #if __cplusplus >= 201103L
   template<typename _Tp, typename _Alloc>
+    _GLIBCXX20_CONSTEXPR
     void
     vector<_Tp, _Alloc>::
     _M_default_append(size_type __n)
@@ -683,6 +698,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
     }
 
   template<typename _Tp, typename _Alloc>
+    _GLIBCXX20_CONSTEXPR
     bool
     vector<_Tp, _Alloc>::
     _M_shrink_to_fit()
@@ -696,6 +712,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 
   template<typename _Tp, typename _Alloc>
     template<typename _InputIterator>
+      _GLIBCXX20_CONSTEXPR
       void
       vector<_Tp, _Alloc>::
       _M_range_insert(iterator __pos, _InputIterator __first,
@@ -717,6 +734,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 
   template<typename _Tp, typename _Alloc>
     template<typename _ForwardIterator>
+      _GLIBCXX20_CONSTEXPR
       void
       vector<_Tp, _Alloc>::
       _M_range_insert(iterator __position, _ForwardIterator __first,
@@ -806,6 +824,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 
   // vector<bool>
   template<typename _Alloc>
+    _GLIBCXX20_CONSTEXPR
     void
     vector<bool, _Alloc>::
     _M_reallocate(size_type __n)
@@ -820,6 +839,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
     }
 
   template<typename _Alloc>
+    _GLIBCXX20_CONSTEXPR
     void
     vector<bool, _Alloc>::
     _M_fill_insert(iterator __position, size_type __n, bool __x)
@@ -852,6 +872,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 
   template<typename _Alloc>
     template<typename _ForwardIterator>
+      _GLIBCXX20_CONSTEXPR
       void
       vector<bool, _Alloc>::
       _M_insert_range(iterator __position, _ForwardIterator __first, 
@@ -886,6 +907,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       }
 
   template<typename _Alloc>
+    _GLIBCXX20_CONSTEXPR
     void
     vector<bool, _Alloc>::
     _M_insert_aux(iterator __position, bool __x)
@@ -914,6 +936,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
     }
 
   template<typename _Alloc>
+    _GLIBCXX20_CONSTEXPR
     typename vector<bool, _Alloc>::iterator
     vector<bool, _Alloc>::
     _M_erase(iterator __position)
@@ -925,6 +948,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
     }
 
   template<typename _Alloc>
+    _GLIBCXX20_CONSTEXPR
     typename vector<bool, _Alloc>::iterator
     vector<bool, _Alloc>::
     _M_erase(iterator __first, iterator __last)
@@ -936,6 +960,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 
 #if __cplusplus >= 201103L
   template<typename _Alloc>
+    _GLIBCXX20_CONSTEXPR
     bool
     vector<bool, _Alloc>::
     _M_shrink_to_fit()
@@ -974,9 +999,6 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     operator()(const _GLIBCXX_STD_C::vector<bool, _Alloc>& __b) const noexcept
     {
       size_t __hash = 0;
-      using _GLIBCXX_STD_C::_S_word_bit;
-      using _GLIBCXX_STD_C::_Bit_type;
-
       const size_t __words = __b.size() / _S_word_bit;
       if (__words)
 	{
diff --git a/libstdc++-v3/include/std/vector b/libstdc++-v3/include/std/vector
index 096511c05b2..890b0ddb3eb 100644
--- a/libstdc++-v3/include/std/vector
+++ b/libstdc++-v3/include/std/vector
@@ -102,6 +102,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #define __cpp_lib_erase_if 202002L
 
   template<typename _Tp, typename _Alloc, typename _Predicate>
+    _GLIBCXX20_CONSTEXPR
     inline typename vector<_Tp, _Alloc>::size_type
     erase_if(vector<_Tp, _Alloc>& __cont, _Predicate __pred)
     {
@@ -115,6 +116,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     }
 
   template<typename _Tp, typename _Alloc, typename _Up>
+    _GLIBCXX20_CONSTEXPR
     inline typename vector<_Tp, _Alloc>::size_type
     erase(vector<_Tp, _Alloc>& __cont, const _Up& __value)
     {
diff --git a/libstdc++-v3/testsuite/23_containers/headers/vector/synopsis.cc b/libstdc++-v3/testsuite/23_containers/headers/vector/synopsis.cc
index 0fc46fe0528..f02659f99be 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 43f3343a578..da5e6b420d2 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 00000000000..52b10b66120
--- /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 7a730df2e18..ae2bd03c2ba 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> );
+
+  return true;
 }
 
-int
-main()
-{
-  test01();
-  test05();
-}
+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 00000000000..edd506081cc
--- /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 00000000000..6fa87588eff
--- /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 00000000000..02faa02f954
--- /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 00000000000..b27df2b2227
--- /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 a2b8c1aa4ad..c67944663cf 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 00000000000..ba444d04ee9
--- /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 00000000000..de9d0b03790
--- /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 0ffacb96f75..8f4a2645e91 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> );
+
+  return true;
 }
 
-int
-main()
-{
-  test01();
-  test02();
-  test03();
-  test04();
-  test05();
-}
+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 302af9c2e97..4f8396fba6d 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 00000000000..24ade4e0800
--- /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 00000000000..f02b39aefad
--- /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 00000000000..45b3167eab0
--- /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 00000000000..9b3b7f634d7
--- /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 00000000000..638cffe9822
--- /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 00000000000..36efecf5807
--- /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 00000000000..4d06558b47b
--- /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());