Message ID | 20231206142930.739485-1-jwakely@redhat.com |
---|---|
State | New |
Headers | show |
Series | libstdc++: Make __gnu_debug::vector usable in constant expressions [PR109536] | expand |
On Wed, 6 Dec 2023 at 14:30, Jonathan Wakely wrote: > > Any comments on this approach? Pushed to trunk now. > > -- >8 -- > > This makes constexpr std::vector (mostly) work in Debug Mode. All safe > iterator instrumentation and checking is disabled during constant > evaluation, because it requires mutex locks and calls to non-inline > functions defined in libstdc++.so. It should be OK to disable the safety > checks, because most UB should be detected during constant evaluation > anyway. > > We could try to enable the full checking in constexpr, but it would mean > wrapping all the non-inline functions like _M_attach with an inline > _M_constexpr_attach that does the iterator housekeeping inline without > mutex locks when calling for constant evaluation, and calls the > non-inline function at runtime. That could be done in future if we find > that we've lost safety or useful checking by disabling the safe > iterators. > > There are a few test failures in C++20 mode, which I'm unable to > explain. The _Safe_iterator::operator++() member gives errors for using > non-constexpr functions during constant evaluation, even though those > functions are guarded by std::is_constant_evaluated() checks. The same > code works fine for C++23 and up. > > libstdc++-v3/ChangeLog: > > PR libstdc++/109536 > * include/bits/c++config (__glibcxx_constexpr_assert): Remove > macro. > * include/bits/stl_algobase.h (__niter_base, __copy_move_a) > (__copy_move_backward_a, __fill_a, __fill_n_a, __equal_aux) > (__lexicographical_compare_aux): Add constexpr to overloads for > debug mode iterators. > * include/debug/helper_functions.h (__unsafe): Add constexpr. > * include/debug/macros.h (_GLIBCXX_DEBUG_VERIFY_COND_AT): Remove > macro, folding it into ... > (_GLIBCXX_DEBUG_VERIFY_AT_F): ... here. Do not use > __glibcxx_constexpr_assert. > * include/debug/safe_base.h (_Safe_iterator_base): Add constexpr > to some member functions. Omit attaching, detaching and checking > operations during constant evaluation. > * include/debug/safe_container.h (_Safe_container): Likewise. > * include/debug/safe_iterator.h (_Safe_iterator): Likewise. > * include/debug/safe_iterator.tcc (__niter_base, __copy_move_a) > (__copy_move_backward_a, __fill_a, __fill_n_a, __equal_aux) > (__lexicographical_compare_aux): Add constexpr. > * include/debug/vector (_Safe_vector, vector): Add constexpr. > Omit safe iterator operations during constant evaluation. > * testsuite/23_containers/vector/bool/capacity/constexpr.cc: > Remove dg-xfail-if for debug mode. > * testsuite/23_containers/vector/bool/cmp_c++20.cc: Likewise. > * testsuite/23_containers/vector/bool/cons/constexpr.cc: > Likewise. > * testsuite/23_containers/vector/bool/element_access/1.cc: > Likewise. > * testsuite/23_containers/vector/bool/element_access/constexpr.cc: > Likewise. > * testsuite/23_containers/vector/bool/modifiers/assign/constexpr.cc: > Likewise. > * testsuite/23_containers/vector/bool/modifiers/constexpr.cc: > Likewise. > * testsuite/23_containers/vector/bool/modifiers/swap/constexpr.cc: > Likewise. > * testsuite/23_containers/vector/capacity/constexpr.cc: > Likewise. > * testsuite/23_containers/vector/cmp_c++20.cc: Likewise. > * testsuite/23_containers/vector/cons/constexpr.cc: Likewise. > * testsuite/23_containers/vector/data_access/constexpr.cc: > Likewise. > * testsuite/23_containers/vector/element_access/constexpr.cc: > Likewise. > * testsuite/23_containers/vector/modifiers/assign/constexpr.cc: > Likewise. > * testsuite/23_containers/vector/modifiers/constexpr.cc: > Likewise. > * testsuite/23_containers/vector/modifiers/swap/constexpr.cc: > Likewise. > --- > libstdc++-v3/include/bits/c++config | 9 - > libstdc++-v3/include/bits/stl_algobase.h | 15 ++ > libstdc++-v3/include/debug/helper_functions.h | 1 + > libstdc++-v3/include/debug/macros.h | 9 +- > libstdc++-v3/include/debug/safe_base.h | 35 +++- > libstdc++-v3/include/debug/safe_container.h | 15 +- > libstdc++-v3/include/debug/safe_iterator.h | 186 +++++++++++++++--- > libstdc++-v3/include/debug/safe_iterator.tcc | 15 ++ > libstdc++-v3/include/debug/vector | 146 ++++++++++++-- > .../vector/bool/capacity/constexpr.cc | 1 - > .../23_containers/vector/bool/cmp_c++20.cc | 1 - > .../vector/bool/cons/constexpr.cc | 1 - > .../vector/bool/element_access/1.cc | 1 - > .../vector/bool/element_access/constexpr.cc | 1 - > .../vector/bool/modifiers/assign/constexpr.cc | 1 - > .../vector/bool/modifiers/constexpr.cc | 1 - > .../vector/bool/modifiers/swap/constexpr.cc | 3 +- > .../vector/capacity/constexpr.cc | 1 - > .../23_containers/vector/cmp_c++20.cc | 1 - > .../23_containers/vector/cons/constexpr.cc | 1 - > .../vector/data_access/constexpr.cc | 1 - > .../vector/element_access/constexpr.cc | 1 - > .../vector/modifiers/assign/constexpr.cc | 1 - > .../vector/modifiers/constexpr.cc | 1 - > .../vector/modifiers/swap/constexpr.cc | 1 - > 25 files changed, 369 insertions(+), 80 deletions(-) > > diff --git a/libstdc++-v3/include/bits/c++config b/libstdc++-v3/include/bits/c++config > index 284d24d933f..13d416845c3 100644 > --- a/libstdc++-v3/include/bits/c++config > +++ b/libstdc++-v3/include/bits/c++config > @@ -565,15 +565,6 @@ namespace std > # define _GLIBCXX_EXTERN_TEMPLATE -1 > #endif > > - > -#if _GLIBCXX_HAVE_IS_CONSTANT_EVALUATED > -# define __glibcxx_constexpr_assert(cond) \ > - if (std::__is_constant_evaluated() && !bool(cond)) \ > - __builtin_unreachable() /* precondition violation detected! */ > -#else > -# define __glibcxx_constexpr_assert(unevaluated) > -#endif > - > #undef _GLIBCXX_VERBOSE_ASSERT > > // Assert. > diff --git a/libstdc++-v3/include/bits/stl_algobase.h b/libstdc++-v3/include/bits/stl_algobase.h > index 01ca4496dfd..77d0ee7bcf5 100644 > --- a/libstdc++-v3/include/bits/stl_algobase.h > +++ b/libstdc++-v3/include/bits/stl_algobase.h > @@ -318,6 +318,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > { return __it; } > > template<typename _Ite, typename _Seq> > + _GLIBCXX20_CONSTEXPR > _Ite > __niter_base(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, > std::random_access_iterator_tag>&); > @@ -545,6 +546,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER > > template<bool _IsMove, > typename _Ite, typename _Seq, typename _Cat, typename _OI> > + _GLIBCXX20_CONSTEXPR > _OI > __copy_move_a(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>&, > const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>&, > @@ -552,6 +554,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER > > template<bool _IsMove, > typename _II, typename _Ite, typename _Seq, typename _Cat> > + _GLIBCXX20_CONSTEXPR > __gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat> > __copy_move_a(_II, _II, > const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>&); > @@ -559,6 +562,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER > template<bool _IsMove, > typename _IIte, typename _ISeq, typename _ICat, > typename _OIte, typename _OSeq, typename _OCat> > + _GLIBCXX20_CONSTEXPR > ::__gnu_debug::_Safe_iterator<_OIte, _OSeq, _OCat> > __copy_move_a(const ::__gnu_debug::_Safe_iterator<_IIte, _ISeq, _ICat>&, > const ::__gnu_debug::_Safe_iterator<_IIte, _ISeq, _ICat>&, > @@ -812,6 +816,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER > > template<bool _IsMove, > typename _Ite, typename _Seq, typename _Cat, typename _OI> > + _GLIBCXX20_CONSTEXPR > _OI > __copy_move_backward_a( > const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>&, > @@ -820,6 +825,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER > > template<bool _IsMove, > typename _II, typename _Ite, typename _Seq, typename _Cat> > + _GLIBCXX20_CONSTEXPR > __gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat> > __copy_move_backward_a(_II, _II, > const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>&); > @@ -827,6 +833,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER > template<bool _IsMove, > typename _IIte, typename _ISeq, typename _ICat, > typename _OIte, typename _OSeq, typename _OCat> > + _GLIBCXX20_CONSTEXPR > ::__gnu_debug::_Safe_iterator<_OIte, _OSeq, _OCat> > __copy_move_backward_a( > const ::__gnu_debug::_Safe_iterator<_IIte, _ISeq, _ICat>&, > @@ -977,6 +984,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER > { std::__fill_a1(__first, __last, __value); } > > template<typename _Ite, typename _Seq, typename _Cat, typename _Tp> > + _GLIBCXX20_CONSTEXPR > void > __fill_a(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>&, > const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>&, > @@ -1082,6 +1090,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER > > template<typename _Ite, typename _Seq, typename _Cat, typename _Size, > typename _Tp> > + _GLIBCXX20_CONSTEXPR > ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat> > __fill_n_a(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>& __first, > _Size __n, const _Tp& __value, > @@ -1230,18 +1239,21 @@ _GLIBCXX_END_NAMESPACE_CONTAINER > } > > template<typename _II1, typename _Seq1, typename _Cat1, typename _II2> > + _GLIBCXX20_CONSTEXPR > bool > __equal_aux(const ::__gnu_debug::_Safe_iterator<_II1, _Seq1, _Cat1>&, > const ::__gnu_debug::_Safe_iterator<_II1, _Seq1, _Cat1>&, > _II2); > > template<typename _II1, typename _II2, typename _Seq2, typename _Cat2> > + _GLIBCXX20_CONSTEXPR > bool > __equal_aux(_II1, _II1, > const ::__gnu_debug::_Safe_iterator<_II2, _Seq2, _Cat2>&); > > template<typename _II1, typename _Seq1, typename _Cat1, > typename _II2, typename _Seq2, typename _Cat2> > + _GLIBCXX20_CONSTEXPR > bool > __equal_aux(const ::__gnu_debug::_Safe_iterator<_II1, _Seq1, _Cat1>&, > const ::__gnu_debug::_Safe_iterator<_II1, _Seq1, _Cat1>&, > @@ -1430,6 +1442,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER > > template<typename _Iter1, typename _Seq1, typename _Cat1, > typename _II2> > + _GLIBCXX20_CONSTEXPR > bool > __lexicographical_compare_aux( > const ::__gnu_debug::_Safe_iterator<_Iter1, _Seq1, _Cat1>&, > @@ -1438,6 +1451,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER > > template<typename _II1, > typename _Iter2, typename _Seq2, typename _Cat2> > + _GLIBCXX20_CONSTEXPR > bool > __lexicographical_compare_aux( > _II1, _II1, > @@ -1446,6 +1460,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER > > template<typename _Iter1, typename _Seq1, typename _Cat1, > typename _Iter2, typename _Seq2, typename _Cat2> > + _GLIBCXX20_CONSTEXPR > bool > __lexicographical_compare_aux( > const ::__gnu_debug::_Safe_iterator<_Iter1, _Seq1, _Cat1>&, > diff --git a/libstdc++-v3/include/debug/helper_functions.h b/libstdc++-v3/include/debug/helper_functions.h > index 052b36b484c..4b76cb00f9a 100644 > --- a/libstdc++-v3/include/debug/helper_functions.h > +++ b/libstdc++-v3/include/debug/helper_functions.h > @@ -324,6 +324,7 @@ namespace __gnu_debug > > /* Remove debug mode safe iterator layer, if any. */ > template<typename _Iterator> > + _GLIBCXX_CONSTEXPR > inline _Iterator > __unsafe(_Iterator __it) > { return __it; } > diff --git a/libstdc++-v3/include/debug/macros.h b/libstdc++-v3/include/debug/macros.h > index 0fef0a006fc..4a3d0f2ea84 100644 > --- a/libstdc++-v3/include/debug/macros.h > +++ b/libstdc++-v3/include/debug/macros.h > @@ -38,15 +38,12 @@ > * the user error and where the error is reported. > * > */ > -#define _GLIBCXX_DEBUG_VERIFY_COND_AT(_Cond,_ErrMsg,_File,_Line,_Func) \ > - if (__builtin_expect(!bool(_Cond), false)) \ > - __gnu_debug::_Error_formatter::_S_at(_File, _Line, _Func) \ > - ._ErrMsg._M_error() > > #define _GLIBCXX_DEBUG_VERIFY_AT_F(_Cond,_ErrMsg,_File,_Line,_Func) \ > do { \ > - __glibcxx_constexpr_assert(_Cond); \ > - _GLIBCXX_DEBUG_VERIFY_COND_AT(_Cond,_ErrMsg,_File,_Line,_Func); \ > + if (__builtin_expect(!bool(_Cond), false)) \ > + __gnu_debug::_Error_formatter::_S_at(_File, _Line, _Func) \ > + ._ErrMsg._M_error(); \ > } while (false) > > #define _GLIBCXX_DEBUG_VERIFY_AT(_Cond,_ErrMsg,_File,_Line) \ > diff --git a/libstdc++-v3/include/debug/safe_base.h b/libstdc++-v3/include/debug/safe_base.h > index 1dfa9f68b65..d9c17b52b48 100644 > --- a/libstdc++-v3/include/debug/safe_base.h > +++ b/libstdc++-v3/include/debug/safe_base.h > @@ -75,6 +75,7 @@ namespace __gnu_debug > > protected: > /** Initializes the iterator and makes it singular. */ > + _GLIBCXX20_CONSTEXPR > _Safe_iterator_base() > : _M_sequence(0), _M_version(0), _M_prior(0), _M_next(0) > { } > @@ -86,18 +87,31 @@ namespace __gnu_debug > * singular. Otherwise, the iterator will reference @p __seq and > * be nonsingular. > */ > + _GLIBCXX20_CONSTEXPR > _Safe_iterator_base(const _Safe_sequence_base* __seq, bool __constant) > : _M_sequence(0), _M_version(0), _M_prior(0), _M_next(0) > - { this->_M_attach(const_cast<_Safe_sequence_base*>(__seq), __constant); } > + { > + if (!std::__is_constant_evaluated()) > + this->_M_attach(const_cast<_Safe_sequence_base*>(__seq), __constant); > + } > > /** Initializes the iterator to reference the same sequence that > @p __x does. @p __constant is true if this is a constant > iterator, and false if it is mutable. */ > + _GLIBCXX20_CONSTEXPR > _Safe_iterator_base(const _Safe_iterator_base& __x, bool __constant) > : _M_sequence(0), _M_version(0), _M_prior(0), _M_next(0) > - { this->_M_attach(__x._M_sequence, __constant); } > + { > + if (!std::__is_constant_evaluated()) > + this->_M_attach(__x._M_sequence, __constant); > + } > > - ~_Safe_iterator_base() { this->_M_detach(); } > + _GLIBCXX20_CONSTEXPR > + ~_Safe_iterator_base() > + { > + if (!std::__is_constant_evaluated()) > + this->_M_detach(); > + } > > /** For use in _Safe_iterator. */ > __gnu_cxx::__mutex& > @@ -201,24 +215,34 @@ namespace __gnu_debug > > protected: > // Initialize with a version number of 1 and no iterators > + _GLIBCXX20_CONSTEXPR > _Safe_sequence_base() _GLIBCXX_NOEXCEPT > : _M_iterators(0), _M_const_iterators(0), _M_version(1) > { } > > #if __cplusplus >= 201103L > + _GLIBCXX20_CONSTEXPR > _Safe_sequence_base(const _Safe_sequence_base&) noexcept > : _Safe_sequence_base() { } > > // Move constructor swap iterators. > + _GLIBCXX20_CONSTEXPR > _Safe_sequence_base(_Safe_sequence_base&& __seq) noexcept > : _Safe_sequence_base() > - { _M_swap(__seq); } > + { > + if (!std::__is_constant_evaluated()) > + _M_swap(__seq); > + } > #endif > > /** Notify all iterators that reference this sequence that the > sequence is being destroyed. */ > + _GLIBCXX20_CONSTEXPR > ~_Safe_sequence_base() > - { this->_M_detach_all(); } > + { > + if (!std::__is_constant_evaluated()) > + this->_M_detach_all(); > + } > > /** Detach all iterators, leaving them singular. */ > void > @@ -244,6 +268,7 @@ namespace __gnu_debug > * operation is complete all iterators that originally referenced > * one container now reference the other container. > */ > + _GLIBCXX20_CONSTEXPR > void > _M_swap(_Safe_sequence_base& __x) _GLIBCXX_USE_NOEXCEPT; > > diff --git a/libstdc++-v3/include/debug/safe_container.h b/libstdc++-v3/include/debug/safe_container.h > index 0d8f64740b0..636156af9f5 100644 > --- a/libstdc++-v3/include/debug/safe_container.h > +++ b/libstdc++-v3/include/debug/safe_container.h > @@ -43,6 +43,7 @@ namespace __gnu_debug > { > typedef _SafeBase<_SafeContainer> _Base; > > + _GLIBCXX20_CONSTEXPR > _SafeContainer& > _M_cont() _GLIBCXX_NOEXCEPT > { return *static_cast<_SafeContainer*>(this); } > @@ -54,20 +55,23 @@ namespace __gnu_debug > _Safe_container(_Safe_container&&) = default; > > private: > + _GLIBCXX20_CONSTEXPR > _Safe_container(_Safe_container&& __x, const _Alloc&, std::true_type) > : _Safe_container(std::move(__x)) > { } > > + _GLIBCXX20_CONSTEXPR > _Safe_container(_Safe_container&& __x, const _Alloc& __a, std::false_type) > : _Safe_container() > { > if (__x._M_cont().get_allocator() == __a) > _Base::_M_swap(__x); > - else > + else if (!std::__is_constant_evaluated()) > __x._M_invalidate_all(); > } > > protected: > + _GLIBCXX20_CONSTEXPR > _Safe_container(_Safe_container&& __x, const _Alloc& __a) > : _Safe_container(std::move(__x), __a, > typename std::allocator_traits<_Alloc>::is_always_equal{}) > @@ -75,17 +79,23 @@ namespace __gnu_debug > #endif > > // Copy assignment invalidate all iterators. > + _GLIBCXX20_CONSTEXPR > _Safe_container& > operator=(const _Safe_container&) _GLIBCXX_NOEXCEPT > { > - this->_M_invalidate_all(); > + if (!std::__is_constant_evaluated()) > + this->_M_invalidate_all(); > return *this; > } > > #if __cplusplus >= 201103L > + _GLIBCXX20_CONSTEXPR > _Safe_container& > operator=(_Safe_container&& __x) noexcept > { > + if (std::__is_constant_evaluated()) > + return *this; > + > if (std::__addressof(__x) == this) > { > // Standard containers have a valid but unspecified value after > @@ -113,6 +123,7 @@ namespace __gnu_debug > return *this; > } > > + _GLIBCXX20_CONSTEXPR > void > _M_swap(_Safe_container& __x) noexcept > { > diff --git a/libstdc++-v3/include/debug/safe_iterator.h b/libstdc++-v3/include/debug/safe_iterator.h > index 693192b3ea9..26f008982f8 100644 > --- a/libstdc++-v3/include/debug/safe_iterator.h > +++ b/libstdc++-v3/include/debug/safe_iterator.h > @@ -40,6 +40,7 @@ > #endif > > #define _GLIBCXX_DEBUG_VERIFY_OPERANDS(_Lhs, _Rhs, _BadMsgId, _DiffMsgId) \ > + if (!std::__is_constant_evaluated()) { \ > _GLIBCXX_DEBUG_VERIFY((!_Lhs._M_singular() && !_Rhs._M_singular()) \ > || (_Lhs._M_value_initialized() \ > && _Rhs._M_value_initialized()), \ > @@ -49,7 +50,8 @@ > _GLIBCXX_DEBUG_VERIFY(_Lhs._M_can_compare(_Rhs), \ > _M_message(_DiffMsgId) \ > ._M_iterator(_Lhs, #_Lhs) \ > - ._M_iterator(_Rhs, #_Rhs)) > + ._M_iterator(_Rhs, #_Rhs)); \ > + } > > #define _GLIBCXX_DEBUG_VERIFY_EQ_OPERANDS(_Lhs, _Rhs) \ > _GLIBCXX_DEBUG_VERIFY_OPERANDS(_Lhs, _Rhs, __msg_iter_compare_bad, \ > @@ -131,9 +133,13 @@ namespace __gnu_debug > > struct _Unchecked { }; > > + _GLIBCXX20_CONSTEXPR > _Safe_iterator(const _Safe_iterator& __x, _Unchecked) _GLIBCXX_NOEXCEPT > : _Iter_base(__x.base()), _Safe_base() > - { _M_attach(__x._M_sequence); } > + { > + if (!std::__is_constant_evaluated()) > + _M_attach(__x._M_sequence); > + } > > public: > typedef _Iterator iterator_type; > @@ -148,6 +154,7 @@ namespace __gnu_debug > #endif > > /// @post the iterator is singular and unattached > + _GLIBCXX20_CONSTEXPR > _Safe_iterator() _GLIBCXX_NOEXCEPT : _Iter_base() { } > > /** > @@ -157,6 +164,7 @@ namespace __gnu_debug > * @pre @p seq is not NULL > * @post this is not singular > */ > + _GLIBCXX20_CONSTEXPR > _Safe_iterator(_Iterator __i, const _Safe_sequence_base* __seq) > _GLIBCXX_NOEXCEPT > : _Iter_base(__i), _Safe_base(__seq, _S_constant()) > @@ -165,9 +173,13 @@ namespace __gnu_debug > /** > * @brief Copy construction. > */ > + _GLIBCXX20_CONSTEXPR > _Safe_iterator(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT > : _Iter_base(__x.base()), _Safe_base() > { > + if (std::__is_constant_evaluated()) > + return; > + > // _GLIBCXX_RESOLVE_LIB_DEFECTS > // DR 408. Is vector<reverse_iterator<char*> > forbidden? > _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() > @@ -183,9 +195,16 @@ namespace __gnu_debug > * @brief Move construction. > * @post __x is singular and unattached > */ > + _GLIBCXX20_CONSTEXPR > _Safe_iterator(_Safe_iterator&& __x) noexcept > : _Iter_base() > { > + if (std::__is_constant_evaluated()) > + { > + base() = __x.base(); > + return; > + } > + > _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() > || __x._M_value_initialized(), > _M_message(__msg_init_copy_singular) > @@ -203,6 +222,7 @@ namespace __gnu_debug > * constant iterator. > */ > template<typename _MutableIterator> > + _GLIBCXX20_CONSTEXPR > _Safe_iterator( > const _Safe_iterator<_MutableIterator, _Sequence, > typename __gnu_cxx::__enable_if<_IsConstant::__value && > @@ -211,6 +231,9 @@ namespace __gnu_debug > _GLIBCXX_NOEXCEPT > : _Iter_base(__x.base()) > { > + if (std::__is_constant_evaluated()) > + return; > + > // _GLIBCXX_RESOLVE_LIB_DEFECTS > // DR 408. Is vector<reverse_iterator<char*> > forbidden? > _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() > @@ -224,9 +247,16 @@ namespace __gnu_debug > /** > * @brief Copy assignment. > */ > + _GLIBCXX20_CONSTEXPR > _Safe_iterator& > operator=(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT > { > + if (std::__is_constant_evaluated()) > + { > + base() = __x.base(); > + return *this; > + } > + > // _GLIBCXX_RESOLVE_LIB_DEFECTS > // DR 408. Is vector<reverse_iterator<char*> > forbidden? > _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() > @@ -256,9 +286,16 @@ namespace __gnu_debug > * @brief Move assignment. > * @post __x is singular and unattached > */ > + _GLIBCXX20_CONSTEXPR > _Safe_iterator& > operator=(_Safe_iterator&& __x) noexcept > { > + if (std::__is_constant_evaluated()) > + { > + base() = __x.base(); > + return *this; > + } > + > _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() > || __x._M_value_initialized(), > _M_message(__msg_copy_singular) > @@ -292,12 +329,16 @@ namespace __gnu_debug > * @pre iterator is dereferenceable > */ > _GLIBCXX_NODISCARD > + _GLIBCXX20_CONSTEXPR > reference > operator*() const _GLIBCXX_NOEXCEPT > { > - _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(), > - _M_message(__msg_bad_deref) > - ._M_iterator(*this, "this")); > + if (!std::__is_constant_evaluated()) > + { > + _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(), > + _M_message(__msg_bad_deref) > + ._M_iterator(*this, "this")); > + } > return *base(); > } > > @@ -306,12 +347,16 @@ namespace __gnu_debug > * @pre iterator is dereferenceable > */ > _GLIBCXX_NODISCARD > + _GLIBCXX20_CONSTEXPR > pointer > operator->() const _GLIBCXX_NOEXCEPT > { > - _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(), > - _M_message(__msg_bad_deref) > - ._M_iterator(*this, "this")); > + if (!std::__is_constant_evaluated()) > + { > + _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(), > + _M_message(__msg_bad_deref) > + ._M_iterator(*this, "this")); > + } > return base().operator->(); > } > > @@ -320,9 +365,16 @@ namespace __gnu_debug > * @brief Iterator preincrement > * @pre iterator is incrementable > */ > + _GLIBCXX20_CONSTEXPR > _Safe_iterator& > operator++() _GLIBCXX_NOEXCEPT > { > + if (std::__is_constant_evaluated()) > + { > + ++base(); > + return *this; > + } > + > _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(), > _M_message(__msg_bad_inc) > ._M_iterator(*this, "this")); > @@ -335,12 +387,16 @@ namespace __gnu_debug > * @brief Iterator postincrement > * @pre iterator is incrementable > */ > + _GLIBCXX20_CONSTEXPR > _Safe_iterator > operator++(int) _GLIBCXX_NOEXCEPT > { > - _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(), > - _M_message(__msg_bad_inc) > - ._M_iterator(*this, "this")); > + if (!std::__is_constant_evaluated()) > + { > + _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(), > + _M_message(__msg_bad_inc) > + ._M_iterator(*this, "this")); > + } > _Safe_iterator __ret(*this, _Unchecked()); > ++*this; > return __ret; > @@ -356,9 +412,11 @@ namespace __gnu_debug > /** > * @brief Return the underlying iterator > */ > + _GLIBCXX20_CONSTEXPR > _Iterator& > base() _GLIBCXX_NOEXCEPT { return *this; } > > + _GLIBCXX20_CONSTEXPR > const _Iterator& > base() const _GLIBCXX_NOEXCEPT { return *this; } > > @@ -366,6 +424,7 @@ namespace __gnu_debug > * @brief Conversion to underlying non-debug iterator to allow > * better interaction with non-debug containers. > */ > + _GLIBCXX20_CONSTEXPR > operator _Iterator() const _GLIBCXX_NOEXCEPT { return *this; } > > /** Attach iterator to the given sequence. */ > @@ -440,6 +499,7 @@ namespace __gnu_debug > _M_get_distance_to_end() const; > > /// Is this iterator equal to the sequence's begin() iterator? > + _GLIBCXX20_CONSTEXPR > bool > _M_is_begin() const > { return base() == _M_get_sequence()->_M_base().begin(); } > @@ -466,6 +526,7 @@ namespace __gnu_debug > typedef _Safe_iterator<_Iterator, _Sequence, iterator_category> _Self; > > _GLIBCXX_NODISCARD > + _GLIBCXX20_CONSTEXPR > friend bool > operator==(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT > { > @@ -475,6 +536,7 @@ namespace __gnu_debug > > template<typename _IteR> > _GLIBCXX_NODISCARD > + _GLIBCXX20_CONSTEXPR > friend bool > operator==(const _Self& __lhs, > const _Safe_iterator<_IteR, _Sequence, iterator_category>& __rhs) > @@ -518,6 +580,7 @@ namespace __gnu_debug > > typedef typename _Safe_base::_Unchecked _Unchecked; > > + _GLIBCXX20_CONSTEXPR > _Safe_iterator(const _Safe_iterator& __x, > _Unchecked __unchecked) _GLIBCXX_NOEXCEPT > : _Safe_base(__x, __unchecked) > @@ -525,6 +588,7 @@ namespace __gnu_debug > > public: > /// @post the iterator is singular and unattached > + _GLIBCXX20_CONSTEXPR > _Safe_iterator() _GLIBCXX_NOEXCEPT { } > > /** > @@ -534,6 +598,7 @@ namespace __gnu_debug > * @pre @p seq is not NULL > * @post this is not singular > */ > + _GLIBCXX20_CONSTEXPR > _Safe_iterator(_Iterator __i, const _Safe_sequence_base* __seq) > _GLIBCXX_NOEXCEPT > : _Safe_base(__i, __seq) > @@ -542,12 +607,14 @@ namespace __gnu_debug > /** > * @brief Copy construction. > */ > + _GLIBCXX20_CONSTEXPR > _Safe_iterator(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT > : _Safe_base(__x) > { } > > #if __cplusplus >= 201103L > /** @brief Move construction. */ > + _GLIBCXX20_CONSTEXPR > _Safe_iterator(_Safe_iterator&&) = default; > #endif > > @@ -556,6 +623,7 @@ namespace __gnu_debug > * constant iterator. > */ > template<typename _MutableIterator> > + _GLIBCXX20_CONSTEXPR > _Safe_iterator( > const _Safe_iterator<_MutableIterator, _Sequence, > typename __gnu_cxx::__enable_if<_Safe_base::_IsConstant::__value && > @@ -588,6 +656,7 @@ namespace __gnu_debug > * @brief Iterator preincrement > * @pre iterator is incrementable > */ > + _GLIBCXX20_CONSTEXPR > _Safe_iterator& > operator++() _GLIBCXX_NOEXCEPT > { > @@ -615,9 +684,16 @@ namespace __gnu_debug > * @brief Iterator predecrement > * @pre iterator is decrementable > */ > + _GLIBCXX20_CONSTEXPR > _Safe_iterator& > operator--() _GLIBCXX_NOEXCEPT > { > + if (std::__is_constant_evaluated()) > + { > + --this->base(); > + return *this; > + } > + > _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(), > _M_message(__msg_bad_dec) > ._M_iterator(*this, "this")); > @@ -663,6 +739,8 @@ namespace __gnu_debug > std::random_access_iterator_tag> _OtherSelf; > > typedef typename _Safe_base::_Unchecked _Unchecked; > + > + _GLIBCXX20_CONSTEXPR > _Safe_iterator(const _Safe_iterator& __x, > _Unchecked __unchecked) _GLIBCXX_NOEXCEPT > : _Safe_base(__x, __unchecked) > @@ -673,6 +751,7 @@ namespace __gnu_debug > typedef typename _Safe_base::reference reference; > > /// @post the iterator is singular and unattached > + _GLIBCXX20_CONSTEXPR > _Safe_iterator() _GLIBCXX_NOEXCEPT { } > > /** > @@ -682,6 +761,7 @@ namespace __gnu_debug > * @pre @p seq is not NULL > * @post this is not singular > */ > + _GLIBCXX20_CONSTEXPR > _Safe_iterator(_Iterator __i, const _Safe_sequence_base* __seq) > _GLIBCXX_NOEXCEPT > : _Safe_base(__i, __seq) > @@ -690,6 +770,7 @@ namespace __gnu_debug > /** > * @brief Copy construction. > */ > + _GLIBCXX20_CONSTEXPR > _Safe_iterator(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT > : _Safe_base(__x) > { } > @@ -704,6 +785,7 @@ namespace __gnu_debug > * constant iterator. > */ > template<typename _MutableIterator> > + _GLIBCXX20_CONSTEXPR > _Safe_iterator( > const _Safe_iterator<_MutableIterator, _Sequence, > typename __gnu_cxx::__enable_if<_Safe_base::_IsConstant::__value && > @@ -742,6 +824,7 @@ namespace __gnu_debug > * @brief Iterator preincrement > * @pre iterator is incrementable > */ > + _GLIBCXX20_CONSTEXPR > _Safe_iterator& > operator++() _GLIBCXX_NOEXCEPT > { > @@ -753,12 +836,16 @@ namespace __gnu_debug > * @brief Iterator postincrement > * @pre iterator is incrementable > */ > + _GLIBCXX20_CONSTEXPR > _Safe_iterator > operator++(int) _GLIBCXX_NOEXCEPT > { > - _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(), > - _M_message(__msg_bad_inc) > - ._M_iterator(*this, "this")); > + if (!std::__is_constant_evaluated()) > + { > + _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(), > + _M_message(__msg_bad_inc) > + ._M_iterator(*this, "this")); > + } > _Safe_iterator __ret(*this, _Unchecked()); > ++*this; > return __ret; > @@ -769,6 +856,7 @@ namespace __gnu_debug > * @brief Iterator predecrement > * @pre iterator is decrementable > */ > + _GLIBCXX20_CONSTEXPR > _Safe_iterator& > operator--() _GLIBCXX_NOEXCEPT > { > @@ -780,12 +868,16 @@ namespace __gnu_debug > * @brief Iterator postdecrement > * @pre iterator is decrementable > */ > + _GLIBCXX20_CONSTEXPR > _Safe_iterator > operator--(int) _GLIBCXX_NOEXCEPT > { > - _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(), > - _M_message(__msg_bad_dec) > - ._M_iterator(*this, "this")); > + if (!std::__is_constant_evaluated()) > + { > + _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(), > + _M_message(__msg_bad_dec) > + ._M_iterator(*this, "this")); > + } > _Safe_iterator __ret(*this, _Unchecked()); > --*this; > return __ret; > @@ -793,19 +885,30 @@ namespace __gnu_debug > > // ------ Random access iterator requirements ------ > _GLIBCXX_NODISCARD > + _GLIBCXX20_CONSTEXPR > reference > operator[](difference_type __n) const _GLIBCXX_NOEXCEPT > { > - _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n) > - && this->_M_can_advance(__n + 1), > - _M_message(__msg_iter_subscript_oob) > - ._M_iterator(*this)._M_integer(__n)); > + if (!std::__is_constant_evaluated()) > + { > + _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n) > + && this->_M_can_advance(__n + 1), > + _M_message(__msg_iter_subscript_oob) > + ._M_iterator(*this)._M_integer(__n)); > + } > return this->base()[__n]; > } > > + _GLIBCXX20_CONSTEXPR > _Safe_iterator& > operator+=(difference_type __n) _GLIBCXX_NOEXCEPT > { > + if (std::__is_constant_evaluated()) > + { > + this->base() += __n; > + return *this; > + } > + > _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n), > _M_message(__msg_advance_oob) > ._M_iterator(*this)._M_integer(__n)); > @@ -814,9 +917,16 @@ namespace __gnu_debug > return *this; > } > > + _GLIBCXX20_CONSTEXPR > _Safe_iterator& > operator-=(difference_type __n) _GLIBCXX_NOEXCEPT > { > + if (std::__is_constant_evaluated()) > + { > + this->base() -= __n; > + return *this; > + } > + > _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(-__n), > _M_message(__msg_retreat_oob) > ._M_iterator(*this)._M_integer(__n)); > @@ -827,6 +937,7 @@ namespace __gnu_debug > > #if __cpp_lib_three_way_comparison > [[nodiscard]] > + _GLIBCXX20_CONSTEXPR > friend auto > operator<=>(const _Self& __lhs, const _Self& __rhs) noexcept > { > @@ -835,6 +946,7 @@ namespace __gnu_debug > } > > [[nodiscard]] > + _GLIBCXX20_CONSTEXPR > friend auto > operator<=>(const _Self& __lhs, const _OtherSelf& __rhs) noexcept > { > @@ -912,6 +1024,7 @@ namespace __gnu_debug > // operators but also operator- must accept mixed iterator/const_iterator > // parameters. > _GLIBCXX_NODISCARD > + _GLIBCXX20_CONSTEXPR > friend difference_type > operator-(const _Self& __lhs, const _OtherSelf& __rhs) _GLIBCXX_NOEXCEPT > { > @@ -920,6 +1033,7 @@ namespace __gnu_debug > } > > _GLIBCXX_NODISCARD > + _GLIBCXX20_CONSTEXPR > friend difference_type > operator-(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT > { > @@ -928,32 +1042,44 @@ namespace __gnu_debug > } > > _GLIBCXX_NODISCARD > + _GLIBCXX20_CONSTEXPR > friend _Self > operator+(const _Self& __x, difference_type __n) _GLIBCXX_NOEXCEPT > { > - _GLIBCXX_DEBUG_VERIFY(__x._M_can_advance(__n), > - _M_message(__msg_advance_oob) > - ._M_iterator(__x)._M_integer(__n)); > + if (!std::__is_constant_evaluated()) > + { > + _GLIBCXX_DEBUG_VERIFY(__x._M_can_advance(__n), > + _M_message(__msg_advance_oob) > + ._M_iterator(__x)._M_integer(__n)); > + } > return _Safe_iterator(__x.base() + __n, __x._M_sequence); > } > > _GLIBCXX_NODISCARD > + _GLIBCXX20_CONSTEXPR > friend _Self > operator+(difference_type __n, const _Self& __x) _GLIBCXX_NOEXCEPT > { > - _GLIBCXX_DEBUG_VERIFY(__x._M_can_advance(__n), > - _M_message(__msg_advance_oob) > - ._M_iterator(__x)._M_integer(__n)); > + if (!std::__is_constant_evaluated()) > + { > + _GLIBCXX_DEBUG_VERIFY(__x._M_can_advance(__n), > + _M_message(__msg_advance_oob) > + ._M_iterator(__x)._M_integer(__n)); > + } > return _Safe_iterator(__n + __x.base(), __x._M_sequence); > } > > _GLIBCXX_NODISCARD > + _GLIBCXX20_CONSTEXPR > friend _Self > operator-(const _Self& __x, difference_type __n) _GLIBCXX_NOEXCEPT > { > - _GLIBCXX_DEBUG_VERIFY(__x._M_can_advance(-__n), > - _M_message(__msg_retreat_oob) > - ._M_iterator(__x)._M_integer(__n)); > + if (!std::__is_constant_evaluated()) > + { > + _GLIBCXX_DEBUG_VERIFY(__x._M_can_advance(-__n), > + _M_message(__msg_retreat_oob) > + ._M_iterator(__x)._M_integer(__n)); > + } > return _Safe_iterator(__x.base() - __n, __x._M_sequence); > } > }; > diff --git a/libstdc++-v3/include/debug/safe_iterator.tcc b/libstdc++-v3/include/debug/safe_iterator.tcc > index 170229ad2f1..0bb3dd017b9 100644 > --- a/libstdc++-v3/include/debug/safe_iterator.tcc > +++ b/libstdc++-v3/include/debug/safe_iterator.tcc > @@ -236,6 +236,7 @@ namespace std _GLIBCXX_VISIBILITY(default) > _GLIBCXX_BEGIN_NAMESPACE_VERSION > > template<typename _Ite, typename _Seq> > + _GLIBCXX20_CONSTEXPR > _Ite > __niter_base(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, > std::random_access_iterator_tag>& __it) > @@ -243,6 +244,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > template<bool _IsMove, > typename _Ite, typename _Seq, typename _Cat, typename _OI> > + _GLIBCXX20_CONSTEXPR > _OI > __copy_move_a( > const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>& __first, > @@ -262,6 +264,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > template<bool _IsMove, > typename _II, typename _Ite, typename _Seq, typename _Cat> > + _GLIBCXX20_CONSTEXPR > __gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat> > __copy_move_a(_II __first, _II __last, > const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>& __result) > @@ -282,6 +285,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > template<bool _IsMove, > typename _IIte, typename _ISeq, typename _ICat, > typename _OIte, typename _OSeq, typename _OCat> > + _GLIBCXX20_CONSTEXPR > ::__gnu_debug::_Safe_iterator<_OIte, _OSeq, _OCat> > __copy_move_a( > const ::__gnu_debug::_Safe_iterator<_IIte, _ISeq, _ICat>& __first, > @@ -310,6 +314,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > template<bool _IsMove, > typename _Ite, typename _Seq, typename _Cat, typename _OI> > + _GLIBCXX20_CONSTEXPR > _OI > __copy_move_backward_a( > const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>& __first, > @@ -329,6 +334,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > template<bool _IsMove, > typename _II, typename _Ite, typename _Seq, typename _Cat> > + _GLIBCXX20_CONSTEXPR > __gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat> > __copy_move_backward_a(_II __first, _II __last, > const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>& __result) > @@ -350,6 +356,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > template<bool _IsMove, > typename _IIte, typename _ISeq, typename _ICat, > typename _OIte, typename _OSeq, typename _OCat> > + _GLIBCXX20_CONSTEXPR > ::__gnu_debug::_Safe_iterator<_OIte, _OSeq, _OCat> > __copy_move_backward_a( > const ::__gnu_debug::_Safe_iterator<_IIte, _ISeq, _ICat>& __first, > @@ -377,6 +384,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > } > > template<typename _Ite, typename _Seq, typename _Cat, typename _Tp> > + _GLIBCXX20_CONSTEXPR > void > __fill_a(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>& __first, > const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>& __last, > @@ -393,6 +401,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > template<typename _Ite, typename _Seq, typename _Cat, typename _Size, > typename _Tp> > + _GLIBCXX20_CONSTEXPR > ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat> > __fill_n_a(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>& __first, > _Size __n, const _Tp& __value, > @@ -415,6 +424,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > } > > template<typename _II1, typename _Seq1, typename _Cat1, typename _II2> > + _GLIBCXX20_CONSTEXPR > bool > __equal_aux( > const ::__gnu_debug::_Safe_iterator<_II1, _Seq1, _Cat1>& __first1, > @@ -432,6 +442,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > } > > template<typename _II1, typename _II2, typename _Seq2, typename _Cat2> > + _GLIBCXX20_CONSTEXPR > bool > __equal_aux(_II1 __first1, _II1 __last1, > const ::__gnu_debug::_Safe_iterator<_II2, _Seq2, _Cat2>& __first2) > @@ -449,6 +460,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > template<typename _II1, typename _Seq1, typename _Cat1, > typename _II2, typename _Seq2, typename _Cat2> > + _GLIBCXX20_CONSTEXPR > bool > __equal_aux( > const ::__gnu_debug::_Safe_iterator<_II1, _Seq1, _Cat1>& __first1, > @@ -473,6 +485,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > template<typename _Ite1, typename _Seq1, typename _Cat1, > typename _II2> > + _GLIBCXX20_CONSTEXPR > bool > __lexicographical_compare_aux( > const ::__gnu_debug::_Safe_iterator<_Ite1, _Seq1, _Cat1>& __first1, > @@ -493,6 +506,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > template<typename _II1, > typename _Ite2, typename _Seq2, typename _Cat2> > + _GLIBCXX20_CONSTEXPR > bool > __lexicographical_compare_aux( > _II1 __first1, _II1 __last1, > @@ -513,6 +527,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > template<typename _Ite1, typename _Seq1, typename _Cat1, > typename _Ite2, typename _Seq2, typename _Cat2> > + _GLIBCXX20_CONSTEXPR > bool > __lexicographical_compare_aux( > const ::__gnu_debug::_Safe_iterator<_Ite1, _Seq1, _Cat1>& __first1, > diff --git a/libstdc++-v3/include/debug/vector b/libstdc++-v3/include/debug/vector > index ed462caf936..124ae6da1c1 100644 > --- a/libstdc++-v3/include/debug/vector > +++ b/libstdc++-v3/include/debug/vector > @@ -55,22 +55,27 @@ namespace __gnu_debug > { > typedef typename _BaseSequence::size_type size_type; > > + _GLIBCXX20_CONSTEXPR > const _SafeSequence& > _M_seq() const { return *static_cast<const _SafeSequence*>(this); } > > protected: > + _GLIBCXX20_CONSTEXPR > _Safe_vector() _GLIBCXX_NOEXCEPT > : _M_guaranteed_capacity(0) > { _M_update_guaranteed_capacity(); } > > + _GLIBCXX20_CONSTEXPR > _Safe_vector(const _Safe_vector&) _GLIBCXX_NOEXCEPT > : _M_guaranteed_capacity(0) > { _M_update_guaranteed_capacity(); } > > + _GLIBCXX20_CONSTEXPR > _Safe_vector(size_type __n) _GLIBCXX_NOEXCEPT > : _M_guaranteed_capacity(__n) > { } > > + _GLIBCXX20_CONSTEXPR > _Safe_vector& > operator=(const _Safe_vector&) _GLIBCXX_NOEXCEPT > { > @@ -79,10 +84,12 @@ namespace __gnu_debug > } > > #if __cplusplus >= 201103L > + _GLIBCXX20_CONSTEXPR > _Safe_vector(_Safe_vector&& __x) noexcept > : _Safe_vector() > { __x._M_guaranteed_capacity = 0; } > > + _GLIBCXX20_CONSTEXPR > _Safe_vector& > operator=(_Safe_vector&& __x) noexcept > { > @@ -98,6 +105,7 @@ namespace __gnu_debug > _M_requires_reallocation(size_type __elements) const _GLIBCXX_NOEXCEPT > { return __elements > _M_seq().capacity(); } > > + _GLIBCXX20_CONSTEXPR > void > _M_update_guaranteed_capacity() _GLIBCXX_NOEXCEPT > { > @@ -172,15 +180,18 @@ namespace __debug > vector() = default; > #endif > > + _GLIBCXX20_CONSTEXPR > explicit > vector(const _Allocator& __a) _GLIBCXX_NOEXCEPT > : _Base(__a) { } > > #if __cplusplus >= 201103L > + _GLIBCXX20_CONSTEXPR > explicit > vector(size_type __n, const _Allocator& __a = _Allocator()) > : _Base(__n, __a), _Safe_vector(__n) { } > > + _GLIBCXX20_CONSTEXPR > vector(size_type __n, const __type_identity_t<_Tp>& __value, > const _Allocator& __a = _Allocator()) > : _Base(__n, __value, __a) { } > @@ -197,10 +208,11 @@ namespace __debug > #else > template<class _InputIterator> > #endif > + _GLIBCXX20_CONSTEXPR > vector(_InputIterator __first, _InputIterator __last, > const _Allocator& __a = _Allocator()) > - : _Base(__gnu_debug::__base( > - __glibcxx_check_valid_constructor_range(__first, __last)), > + : _Base(__gnu_debug::__base(std::__is_constant_evaluated() ? __first > + : __glibcxx_check_valid_constructor_range(__first, __last)), > __gnu_debug::__base(__last), __a) { } > > #if __cplusplus < 201103L > @@ -212,9 +224,11 @@ namespace __debug > vector(const vector&) = default; > vector(vector&&) = default; > > + _GLIBCXX20_CONSTEXPR > vector(const vector& __x, const __type_identity_t<allocator_type>& __a) > : _Base(__x, __a) { } > > + _GLIBCXX20_CONSTEXPR > vector(vector&& __x, const __type_identity_t<allocator_type>& __a) > noexcept( > std::is_nothrow_constructible<_Base, > @@ -223,6 +237,7 @@ namespace __debug > _Base(std::move(__x), __a), > _Safe_vector(std::move(__x)) { } > > + _GLIBCXX20_CONSTEXPR > vector(initializer_list<value_type> __l, > const allocator_type& __a = allocator_type()) > : _Base(__l, __a) { } > @@ -231,6 +246,7 @@ namespace __debug > #endif > > /// Construction from a normal-mode vector > + _GLIBCXX20_CONSTEXPR > vector(_Base_ref __x) > : _Base(__x._M_ref) { } > > @@ -241,12 +257,16 @@ namespace __debug > vector& > operator=(vector&&) = default; > > + _GLIBCXX20_CONSTEXPR > vector& > operator=(initializer_list<value_type> __l) > { > _Base::operator=(__l); > - this->_M_invalidate_all(); > - this->_M_update_guaranteed_capacity(); > + if (!std::__is_constant_evaluated()) > + { > + this->_M_invalidate_all(); > + this->_M_update_guaranteed_capacity(); > + } > return *this; > } > #endif > @@ -257,9 +277,14 @@ namespace __debug > #else > template<typename _InputIterator> > #endif > + _GLIBCXX20_CONSTEXPR > void > assign(_InputIterator __first, _InputIterator __last) > { > + if (std::__is_constant_evaluated()) > + return _Base::assign(__gnu_debug::__unsafe(__first), > + __gnu_debug::__unsafe(__last)); > + > typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist; > __glibcxx_check_valid_range2(__first, __last, __dist); > > @@ -273,21 +298,29 @@ namespace __debug > this->_M_update_guaranteed_capacity(); > } > > + _GLIBCXX20_CONSTEXPR > void > assign(size_type __n, const _Tp& __u) > { > _Base::assign(__n, __u); > - this->_M_invalidate_all(); > - this->_M_update_guaranteed_capacity(); > + if (!std::__is_constant_evaluated()) > + { > + this->_M_invalidate_all(); > + this->_M_update_guaranteed_capacity(); > + } > } > > #if __cplusplus >= 201103L > + _GLIBCXX20_CONSTEXPR > void > assign(initializer_list<value_type> __l) > { > _Base::assign(__l); > - this->_M_invalidate_all(); > - this->_M_update_guaranteed_capacity(); > + if (!std::__is_constant_evaluated()) > + { > + this->_M_invalidate_all(); > + this->_M_update_guaranteed_capacity(); > + } > } > #endif > > @@ -295,62 +328,74 @@ namespace __debug > > // iterators: > _GLIBCXX_NODISCARD > + _GLIBCXX20_CONSTEXPR > iterator > begin() _GLIBCXX_NOEXCEPT > { return iterator(_Base::begin(), this); } > > _GLIBCXX_NODISCARD > + _GLIBCXX20_CONSTEXPR > const_iterator > begin() const _GLIBCXX_NOEXCEPT > { return const_iterator(_Base::begin(), this); } > > _GLIBCXX_NODISCARD > + _GLIBCXX20_CONSTEXPR > iterator > end() _GLIBCXX_NOEXCEPT > { return iterator(_Base::end(), this); } > > _GLIBCXX_NODISCARD > + _GLIBCXX20_CONSTEXPR > const_iterator > end() const _GLIBCXX_NOEXCEPT > { return const_iterator(_Base::end(), this); } > > _GLIBCXX_NODISCARD > + _GLIBCXX20_CONSTEXPR > reverse_iterator > rbegin() _GLIBCXX_NOEXCEPT > { return reverse_iterator(end()); } > > _GLIBCXX_NODISCARD > + _GLIBCXX20_CONSTEXPR > const_reverse_iterator > rbegin() const _GLIBCXX_NOEXCEPT > { return const_reverse_iterator(end()); } > > _GLIBCXX_NODISCARD > + _GLIBCXX20_CONSTEXPR > reverse_iterator > rend() _GLIBCXX_NOEXCEPT > { return reverse_iterator(begin()); } > > _GLIBCXX_NODISCARD > + _GLIBCXX20_CONSTEXPR > const_reverse_iterator > rend() const _GLIBCXX_NOEXCEPT > { return const_reverse_iterator(begin()); } > > #if __cplusplus >= 201103L > [[__nodiscard__]] > + _GLIBCXX20_CONSTEXPR > const_iterator > cbegin() const noexcept > { return const_iterator(_Base::begin(), this); } > > [[__nodiscard__]] > + _GLIBCXX20_CONSTEXPR > const_iterator > cend() const noexcept > { return const_iterator(_Base::end(), this); } > > [[__nodiscard__]] > + _GLIBCXX20_CONSTEXPR > const_reverse_iterator > crbegin() const noexcept > { return const_reverse_iterator(end()); } > > [[__nodiscard__]] > + _GLIBCXX20_CONSTEXPR > const_reverse_iterator > crend() const noexcept > { return const_reverse_iterator(begin()); } > @@ -361,9 +406,13 @@ namespace __debug > using _Base::max_size; > > #if __cplusplus >= 201103L > + _GLIBCXX20_CONSTEXPR > void > resize(size_type __sz) > { > + if (std::__is_constant_evaluated()) > + return _Base::resize(__sz); > + > bool __realloc = this->_M_requires_reallocation(__sz); > if (__sz < this->size()) > this->_M_invalidate_after_nth(__sz); > @@ -373,9 +422,13 @@ namespace __debug > this->_M_update_guaranteed_capacity(); > } > > + _GLIBCXX20_CONSTEXPR > void > resize(size_type __sz, const _Tp& __c) > { > + if (std::__is_constant_evaluated()) > + return _Base::resize(__sz, __c); > + > bool __realloc = this->_M_requires_reallocation(__sz); > if (__sz < this->size()) > this->_M_invalidate_after_nth(__sz); > @@ -399,9 +452,13 @@ namespace __debug > #endif > > #if __cplusplus >= 201103L > + _GLIBCXX20_CONSTEXPR > void > shrink_to_fit() > { > + if (std::__is_constant_evaluated()) > + return _Base::shrink_to_fit(); > + > if (_Base::_M_shrink_to_fit()) > { > this->_M_guaranteed_capacity = _Base::capacity(); > @@ -411,9 +468,13 @@ namespace __debug > #endif > > _GLIBCXX_NODISCARD > + _GLIBCXX20_CONSTEXPR > size_type > capacity() const _GLIBCXX_NOEXCEPT > { > + if (std::__is_constant_evaluated()) > + return _Base::capacity(); > + > #ifdef _GLIBCXX_DEBUG_PEDANTIC > return this->_M_guaranteed_capacity; > #else > @@ -423,9 +484,13 @@ namespace __debug > > using _Base::empty; > > + _GLIBCXX20_CONSTEXPR > void > reserve(size_type __n) > { > + if (std::__is_constant_evaluated()) > + return _Base::reserve(__n); > + > bool __realloc = this->_M_requires_reallocation(__n); > _Base::reserve(__n); > if (__n > this->_M_guaranteed_capacity) > @@ -436,6 +501,7 @@ namespace __debug > > // element access: > _GLIBCXX_NODISCARD > + _GLIBCXX20_CONSTEXPR > reference > operator[](size_type __n) _GLIBCXX_NOEXCEPT > { > @@ -444,6 +510,7 @@ namespace __debug > } > > _GLIBCXX_NODISCARD > + _GLIBCXX20_CONSTEXPR > const_reference > operator[](size_type __n) const _GLIBCXX_NOEXCEPT > { > @@ -454,6 +521,7 @@ namespace __debug > using _Base::at; > > _GLIBCXX_NODISCARD > + _GLIBCXX20_CONSTEXPR > reference > front() _GLIBCXX_NOEXCEPT > { > @@ -462,6 +530,7 @@ namespace __debug > } > > _GLIBCXX_NODISCARD > + _GLIBCXX20_CONSTEXPR > const_reference > front() const _GLIBCXX_NOEXCEPT > { > @@ -470,6 +539,7 @@ namespace __debug > } > > _GLIBCXX_NODISCARD > + _GLIBCXX20_CONSTEXPR > reference > back() _GLIBCXX_NOEXCEPT > { > @@ -478,6 +548,7 @@ namespace __debug > } > > _GLIBCXX_NODISCARD > + _GLIBCXX20_CONSTEXPR > const_reference > back() const _GLIBCXX_NOEXCEPT > { > @@ -490,9 +561,13 @@ namespace __debug > using _Base::data; > > // 23.2.4.3 modifiers: > + _GLIBCXX20_CONSTEXPR > void > push_back(const _Tp& __x) > { > + if (std::__is_constant_evaluated()) > + return _Base::push_back(__x); > + > bool __realloc = this->_M_requires_reallocation(this->size() + 1); > _Base::push_back(__x); > if (__realloc) > @@ -502,12 +577,14 @@ namespace __debug > > #if __cplusplus >= 201103L > template<typename _Up = _Tp> > + _GLIBCXX20_CONSTEXPR > typename __gnu_cxx::__enable_if<!std::__are_same<_Up, bool>::__value, > void>::__type > push_back(_Tp&& __x) > { emplace_back(std::move(__x)); } > > template<typename... _Args> > + _GLIBCXX20_CONSTEXPR > #if __cplusplus > 201402L > reference > #else > @@ -515,6 +592,9 @@ namespace __debug > #endif > emplace_back(_Args&&... __args) > { > + if (std::__is_constant_evaluated()) > + return _Base::emplace_back(std::forward<_Args>(__args)...); > + > bool __realloc = this->_M_requires_reallocation(this->size() + 1); > _Base::emplace_back(std::forward<_Args>(__args)...); > if (__realloc) > @@ -526,19 +606,29 @@ namespace __debug > } > #endif > > + _GLIBCXX20_CONSTEXPR > void > pop_back() _GLIBCXX_NOEXCEPT > { > - __glibcxx_check_nonempty(); > - this->_M_invalidate_if(_Equal(--_Base::end())); > + if (!std::__is_constant_evaluated()) > + { > + __glibcxx_check_nonempty(); > + this->_M_invalidate_if(_Equal(--_Base::end())); > + } > _Base::pop_back(); > } > > #if __cplusplus >= 201103L > template<typename... _Args> > + _GLIBCXX20_CONSTEXPR > iterator > emplace(const_iterator __position, _Args&&... __args) > { > + if (std::__is_constant_evaluated()) > + return iterator(_Base::emplace(__position.base(), > + std::forward<_Args>(__args)...), > + this); > + > __glibcxx_check_insert(__position); > bool __realloc = this->_M_requires_reallocation(this->size() + 1); > difference_type __offset = __position.base() - _Base::cbegin(); > @@ -553,6 +643,7 @@ namespace __debug > } > #endif > > + _GLIBCXX20_CONSTEXPR > iterator > #if __cplusplus >= 201103L > insert(const_iterator __position, const _Tp& __x) > @@ -560,6 +651,9 @@ namespace __debug > insert(iterator __position, const _Tp& __x) > #endif > { > + if (std::__is_constant_evaluated()) > + return iterator(_Base::insert(__position.base(), __x), this); > + > __glibcxx_check_insert(__position); > bool __realloc = this->_M_requires_reallocation(this->size() + 1); > difference_type __offset = __position.base() - _Base::begin(); > @@ -574,20 +668,26 @@ namespace __debug > > #if __cplusplus >= 201103L > template<typename _Up = _Tp> > + _GLIBCXX20_CONSTEXPR > typename __gnu_cxx::__enable_if<!std::__are_same<_Up, bool>::__value, > iterator>::__type > insert(const_iterator __position, _Tp&& __x) > { return emplace(__position, std::move(__x)); } > > + _GLIBCXX20_CONSTEXPR > iterator > insert(const_iterator __position, initializer_list<value_type> __l) > { return this->insert(__position, __l.begin(), __l.end()); } > #endif > > #if __cplusplus >= 201103L > + _GLIBCXX20_CONSTEXPR > iterator > insert(const_iterator __position, size_type __n, const _Tp& __x) > { > + if (std::__is_constant_evaluated()) > + return iterator(_Base::insert(__position.base(), __n, __x), this); > + > __glibcxx_check_insert(__position); > bool __realloc = this->_M_requires_reallocation(this->size() + __n); > difference_type __offset = __position.base() - _Base::cbegin(); > @@ -618,10 +718,16 @@ namespace __debug > #if __cplusplus >= 201103L > template<class _InputIterator, > typename = std::_RequireInputIter<_InputIterator>> > + _GLIBCXX20_CONSTEXPR > iterator > insert(const_iterator __position, > _InputIterator __first, _InputIterator __last) > { > + if (std::__is_constant_evaluated()) > + return iterator(_Base::insert(__position.base(), > + __gnu_debug::__unsafe(__first), > + __gnu_debug::__unsafe(__last)), this); > + > typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist; > __glibcxx_check_insert_range(__position, __first, __last, __dist); > > @@ -673,6 +779,7 @@ namespace __debug > } > #endif > > + _GLIBCXX20_CONSTEXPR > iterator > #if __cplusplus >= 201103L > erase(const_iterator __position) > @@ -680,6 +787,9 @@ namespace __debug > erase(iterator __position) > #endif > { > + if (std::__is_constant_evaluated()) > + return iterator(_Base::erase(__position.base()), this); > + > __glibcxx_check_erase(__position); > difference_type __offset = __position.base() - _Base::begin(); > _Base_iterator __res = _Base::erase(__position.base()); > @@ -687,6 +797,7 @@ namespace __debug > return iterator(__res, this); > } > > + _GLIBCXX20_CONSTEXPR > iterator > #if __cplusplus >= 201103L > erase(const_iterator __first, const_iterator __last) > @@ -694,6 +805,9 @@ namespace __debug > erase(iterator __first, iterator __last) > #endif > { > + if (std::__is_constant_evaluated()) > + return iterator(_Base::erase(__first.base(), __last.base()), this); > + > // _GLIBCXX_RESOLVE_LIB_DEFECTS > // 151. can't currently clear() empty container > __glibcxx_check_erase_range(__first, __last); > @@ -714,25 +828,31 @@ namespace __debug > #endif > } > > + _GLIBCXX20_CONSTEXPR > void > swap(vector& __x) > _GLIBCXX_NOEXCEPT_IF( noexcept(declval<_Base&>().swap(__x)) ) > { > - _Safe::_M_swap(__x); > + if (!std::__is_constant_evaluated()) > + _Safe::_M_swap(__x); > _Base::swap(__x); > std::swap(this->_M_guaranteed_capacity, __x._M_guaranteed_capacity); > } > > + _GLIBCXX20_CONSTEXPR > void > clear() _GLIBCXX_NOEXCEPT > { > _Base::clear(); > - this->_M_invalidate_all(); > + if (!std::__is_constant_evaluated()) > + this->_M_invalidate_all(); > } > > + _GLIBCXX20_CONSTEXPR > _Base& > _M_base() _GLIBCXX_NOEXCEPT { return *this; } > > + _GLIBCXX20_CONSTEXPR > const _Base& > _M_base() const _GLIBCXX_NOEXCEPT { return *this; } > > @@ -746,6 +866,7 @@ namespace __debug > }; > > template<typename _Tp, typename _Alloc> > + _GLIBCXX20_CONSTEXPR > inline bool > operator==(const vector<_Tp, _Alloc>& __lhs, > const vector<_Tp, _Alloc>& __rhs) > @@ -789,6 +910,7 @@ namespace __debug > #endif // three-way comparison > > template<typename _Tp, typename _Alloc> > + _GLIBCXX20_CONSTEXPR > inline void > swap(vector<_Tp, _Alloc>& __lhs, vector<_Tp, _Alloc>& __rhs) > _GLIBCXX_NOEXCEPT_IF(noexcept(__lhs.swap(__rhs))) > diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/capacity/constexpr.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/capacity/constexpr.cc > index d44e9d97b46..534128c487e 100644 > --- a/libstdc++-v3/testsuite/23_containers/vector/bool/capacity/constexpr.cc > +++ b/libstdc++-v3/testsuite/23_containers/vector/bool/capacity/constexpr.cc > @@ -1,5 +1,4 @@ > // { dg-do compile { target c++20 } } > -// { dg-xfail-if "not supported" { debug_mode } } > > #include <vector> > #include <testsuite_hooks.h> > 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 66197e0aa29..e852c388903 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,7 +16,6 @@ > // <http://www.gnu.org/licenses/>. > > // { dg-do compile { target c++20 } } > -// { dg-xfail-if "not supported" { debug_mode } } > > #include <vector> > #include <testsuite_hooks.h> > diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/cons/constexpr.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/cons/constexpr.cc > index 0e0c1e1c5ec..88d99fe682f 100644 > --- a/libstdc++-v3/testsuite/23_containers/vector/bool/cons/constexpr.cc > +++ b/libstdc++-v3/testsuite/23_containers/vector/bool/cons/constexpr.cc > @@ -1,5 +1,4 @@ > // { dg-do compile { target c++20 } } > -// { dg-xfail-if "not supported" { debug_mode } } > > #include <vector> > #include <testsuite_hooks.h> > diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/element_access/1.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/element_access/1.cc > index 2a430845058..e7d710829e1 100644 > --- a/libstdc++-v3/testsuite/23_containers/vector/bool/element_access/1.cc > +++ b/libstdc++-v3/testsuite/23_containers/vector/bool/element_access/1.cc > @@ -1,5 +1,4 @@ > // { dg-do compile { target c++23 } } > -// { dg-xfail-if "not supported" { debug_mode } } > > #include <vector> > #include <testsuite_hooks.h> > 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 > index 5b8ca94e78f..d6b657e0161 100644 > --- a/libstdc++-v3/testsuite/23_containers/vector/bool/element_access/constexpr.cc > +++ b/libstdc++-v3/testsuite/23_containers/vector/bool/element_access/constexpr.cc > @@ -1,5 +1,4 @@ > // { dg-do compile { target c++20 } } > -// { dg-xfail-if "not supported" { debug_mode } } > > #include <vector> > #include <testsuite_hooks.h> > 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 > index 3ad7dda88a9..31a6793f7ff 100644 > --- a/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/assign/constexpr.cc > +++ b/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/assign/constexpr.cc > @@ -1,5 +1,4 @@ > // { dg-do compile { target c++20 } } > -// { dg-xfail-if "not supported" { debug_mode } } > > #include <vector> > #include <testsuite_hooks.h> > diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/constexpr.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/constexpr.cc > index 22a4df5e370..0e37f9aa786 100644 > --- a/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/constexpr.cc > +++ b/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/constexpr.cc > @@ -1,5 +1,4 @@ > // { dg-do compile { target c++20 } } > -// { dg-xfail-if "not supported" { debug_mode } } > > #include <vector> > #include <testsuite_hooks.h> > 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 > index 624ff96a9e9..d2a0218a109 100644 > --- a/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/swap/constexpr.cc > +++ b/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/swap/constexpr.cc > @@ -1,5 +1,4 @@ > // { dg-do compile { target c++20 } } > -// { dg-xfail-if "not supported" { debug_mode } } > > #include <vector> > #include <utility> > @@ -49,6 +48,7 @@ test_member_swap() > > static_assert(test_member_swap()); > > +#ifndef _GLIBCXX_DEBUG > constexpr bool > test_reference_swap() > { > @@ -63,3 +63,4 @@ test_reference_swap() > } > > static_assert(test_reference_swap()); > +#endif > diff --git a/libstdc++-v3/testsuite/23_containers/vector/capacity/constexpr.cc b/libstdc++-v3/testsuite/23_containers/vector/capacity/constexpr.cc > index 018a4792891..c331dbd5e57 100644 > --- a/libstdc++-v3/testsuite/23_containers/vector/capacity/constexpr.cc > +++ b/libstdc++-v3/testsuite/23_containers/vector/capacity/constexpr.cc > @@ -1,5 +1,4 @@ > // { dg-do compile { target c++20 } } > -// { dg-xfail-if "not supported" { debug_mode } } > > #include <vector> > #include <testsuite_hooks.h> > 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 72c5c6cd7f9..63cb92c0edf 100644 > --- a/libstdc++-v3/testsuite/23_containers/vector/cmp_c++20.cc > +++ b/libstdc++-v3/testsuite/23_containers/vector/cmp_c++20.cc > @@ -16,7 +16,6 @@ > // <http://www.gnu.org/licenses/>. > > // { dg-do compile { target c++20 } } > -// { dg-xfail-if "not supported" { debug_mode } } > > #include <vector> > #include <testsuite_hooks.h> > diff --git a/libstdc++-v3/testsuite/23_containers/vector/cons/constexpr.cc b/libstdc++-v3/testsuite/23_containers/vector/cons/constexpr.cc > index 7bf86511240..fa78676b300 100644 > --- a/libstdc++-v3/testsuite/23_containers/vector/cons/constexpr.cc > +++ b/libstdc++-v3/testsuite/23_containers/vector/cons/constexpr.cc > @@ -1,6 +1,5 @@ > // { dg-do compile { target c++20 } } > // { dg-add-options no_pch } > -// { dg-xfail-if "not supported" { debug_mode } } > > #include <vector> > > diff --git a/libstdc++-v3/testsuite/23_containers/vector/data_access/constexpr.cc b/libstdc++-v3/testsuite/23_containers/vector/data_access/constexpr.cc > index f5b601a44f4..142050e8f03 100644 > --- a/libstdc++-v3/testsuite/23_containers/vector/data_access/constexpr.cc > +++ b/libstdc++-v3/testsuite/23_containers/vector/data_access/constexpr.cc > @@ -1,5 +1,4 @@ > // { dg-do compile { target c++20 } } > -// { dg-xfail-if "not supported" { debug_mode } } > > #include <vector> > #include <testsuite_hooks.h> > diff --git a/libstdc++-v3/testsuite/23_containers/vector/element_access/constexpr.cc b/libstdc++-v3/testsuite/23_containers/vector/element_access/constexpr.cc > index 60c66dcc647..ee93d2fd95e 100644 > --- a/libstdc++-v3/testsuite/23_containers/vector/element_access/constexpr.cc > +++ b/libstdc++-v3/testsuite/23_containers/vector/element_access/constexpr.cc > @@ -1,5 +1,4 @@ > // { dg-do compile { target c++20 } } > -// { dg-xfail-if "not supported" { debug_mode } } > > #include <vector> > #include <testsuite_hooks.h> > diff --git a/libstdc++-v3/testsuite/23_containers/vector/modifiers/assign/constexpr.cc b/libstdc++-v3/testsuite/23_containers/vector/modifiers/assign/constexpr.cc > index cca20f4291c..41fc8d9696e 100644 > --- a/libstdc++-v3/testsuite/23_containers/vector/modifiers/assign/constexpr.cc > +++ b/libstdc++-v3/testsuite/23_containers/vector/modifiers/assign/constexpr.cc > @@ -1,5 +1,4 @@ > // { dg-do compile { target c++20 } } > -// { dg-xfail-if "not supported" { debug_mode } } > > #include <vector> > #include <testsuite_hooks.h> > diff --git a/libstdc++-v3/testsuite/23_containers/vector/modifiers/constexpr.cc b/libstdc++-v3/testsuite/23_containers/vector/modifiers/constexpr.cc > index 766e3a7690f..4aa1f1f67b7 100644 > --- a/libstdc++-v3/testsuite/23_containers/vector/modifiers/constexpr.cc > +++ b/libstdc++-v3/testsuite/23_containers/vector/modifiers/constexpr.cc > @@ -1,5 +1,4 @@ > // { dg-do compile { target c++20 } } > -// { dg-xfail-if "not supported" { debug_mode } } > > #include <vector> > #include <testsuite_hooks.h> > diff --git a/libstdc++-v3/testsuite/23_containers/vector/modifiers/swap/constexpr.cc b/libstdc++-v3/testsuite/23_containers/vector/modifiers/swap/constexpr.cc > index 45b3986beca..77d2a518d69 100644 > --- a/libstdc++-v3/testsuite/23_containers/vector/modifiers/swap/constexpr.cc > +++ b/libstdc++-v3/testsuite/23_containers/vector/modifiers/swap/constexpr.cc > @@ -1,5 +1,4 @@ > // { dg-do compile { target c++20 } } > -// { dg-xfail-if "not supported" { debug_mode } } > > #include <vector> > #include <utility> > -- > 2.43.0 >
On Wed, 6 Dec 2023, Jonathan Wakely wrote: > Any comments on this approach? > > -- >8 -- > > This makes constexpr std::vector (mostly) work in Debug Mode. All safe > iterator instrumentation and checking is disabled during constant > evaluation, because it requires mutex locks and calls to non-inline > functions defined in libstdc++.so. It should be OK to disable the safety > checks, because most UB should be detected during constant evaluation > anyway. > > We could try to enable the full checking in constexpr, but it would mean > wrapping all the non-inline functions like _M_attach with an inline > _M_constexpr_attach that does the iterator housekeeping inline without > mutex locks when calling for constant evaluation, and calls the > non-inline function at runtime. That could be done in future if we find > that we've lost safety or useful checking by disabling the safe > iterators. > > There are a few test failures in C++20 mode, which I'm unable to > explain. The _Safe_iterator::operator++() member gives errors for using > non-constexpr functions during constant evaluation, even though those > functions are guarded by std::is_constant_evaluated() checks. The same > code works fine for C++23 and up. AFAICT these C++20 test failures are really due to the variable definition of non-literal type 381 __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); which were prohibited in a constexpr function (even if that code was never executed) until C++23's P2242R3. We can use an immediately invoked lambda to work around this: 381 [this] { 382 __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); 383 ++base(); 384 }(); 385 return *this; > > libstdc++-v3/ChangeLog: > > PR libstdc++/109536 > * include/bits/c++config (__glibcxx_constexpr_assert): Remove > macro. > * include/bits/stl_algobase.h (__niter_base, __copy_move_a) > (__copy_move_backward_a, __fill_a, __fill_n_a, __equal_aux) > (__lexicographical_compare_aux): Add constexpr to overloads for > debug mode iterators. > * include/debug/helper_functions.h (__unsafe): Add constexpr. > * include/debug/macros.h (_GLIBCXX_DEBUG_VERIFY_COND_AT): Remove > macro, folding it into ... > (_GLIBCXX_DEBUG_VERIFY_AT_F): ... here. Do not use > __glibcxx_constexpr_assert. > * include/debug/safe_base.h (_Safe_iterator_base): Add constexpr > to some member functions. Omit attaching, detaching and checking > operations during constant evaluation. > * include/debug/safe_container.h (_Safe_container): Likewise. > * include/debug/safe_iterator.h (_Safe_iterator): Likewise. > * include/debug/safe_iterator.tcc (__niter_base, __copy_move_a) > (__copy_move_backward_a, __fill_a, __fill_n_a, __equal_aux) > (__lexicographical_compare_aux): Add constexpr. > * include/debug/vector (_Safe_vector, vector): Add constexpr. > Omit safe iterator operations during constant evaluation. > * testsuite/23_containers/vector/bool/capacity/constexpr.cc: > Remove dg-xfail-if for debug mode. > * testsuite/23_containers/vector/bool/cmp_c++20.cc: Likewise. > * testsuite/23_containers/vector/bool/cons/constexpr.cc: > Likewise. > * testsuite/23_containers/vector/bool/element_access/1.cc: > Likewise. > * testsuite/23_containers/vector/bool/element_access/constexpr.cc: > Likewise. > * testsuite/23_containers/vector/bool/modifiers/assign/constexpr.cc: > Likewise. > * testsuite/23_containers/vector/bool/modifiers/constexpr.cc: > Likewise. > * testsuite/23_containers/vector/bool/modifiers/swap/constexpr.cc: > Likewise. > * testsuite/23_containers/vector/capacity/constexpr.cc: > Likewise. > * testsuite/23_containers/vector/cmp_c++20.cc: Likewise. > * testsuite/23_containers/vector/cons/constexpr.cc: Likewise. > * testsuite/23_containers/vector/data_access/constexpr.cc: > Likewise. > * testsuite/23_containers/vector/element_access/constexpr.cc: > Likewise. > * testsuite/23_containers/vector/modifiers/assign/constexpr.cc: > Likewise. > * testsuite/23_containers/vector/modifiers/constexpr.cc: > Likewise. > * testsuite/23_containers/vector/modifiers/swap/constexpr.cc: > Likewise. > --- > libstdc++-v3/include/bits/c++config | 9 - > libstdc++-v3/include/bits/stl_algobase.h | 15 ++ > libstdc++-v3/include/debug/helper_functions.h | 1 + > libstdc++-v3/include/debug/macros.h | 9 +- > libstdc++-v3/include/debug/safe_base.h | 35 +++- > libstdc++-v3/include/debug/safe_container.h | 15 +- > libstdc++-v3/include/debug/safe_iterator.h | 186 +++++++++++++++--- > libstdc++-v3/include/debug/safe_iterator.tcc | 15 ++ > libstdc++-v3/include/debug/vector | 146 ++++++++++++-- > .../vector/bool/capacity/constexpr.cc | 1 - > .../23_containers/vector/bool/cmp_c++20.cc | 1 - > .../vector/bool/cons/constexpr.cc | 1 - > .../vector/bool/element_access/1.cc | 1 - > .../vector/bool/element_access/constexpr.cc | 1 - > .../vector/bool/modifiers/assign/constexpr.cc | 1 - > .../vector/bool/modifiers/constexpr.cc | 1 - > .../vector/bool/modifiers/swap/constexpr.cc | 3 +- > .../vector/capacity/constexpr.cc | 1 - > .../23_containers/vector/cmp_c++20.cc | 1 - > .../23_containers/vector/cons/constexpr.cc | 1 - > .../vector/data_access/constexpr.cc | 1 - > .../vector/element_access/constexpr.cc | 1 - > .../vector/modifiers/assign/constexpr.cc | 1 - > .../vector/modifiers/constexpr.cc | 1 - > .../vector/modifiers/swap/constexpr.cc | 1 - > 25 files changed, 369 insertions(+), 80 deletions(-) > > diff --git a/libstdc++-v3/include/bits/c++config b/libstdc++-v3/include/bits/c++config > index 284d24d933f..13d416845c3 100644 > --- a/libstdc++-v3/include/bits/c++config > +++ b/libstdc++-v3/include/bits/c++config > @@ -565,15 +565,6 @@ namespace std > # define _GLIBCXX_EXTERN_TEMPLATE -1 > #endif > > - > -#if _GLIBCXX_HAVE_IS_CONSTANT_EVALUATED > -# define __glibcxx_constexpr_assert(cond) \ > - if (std::__is_constant_evaluated() && !bool(cond)) \ > - __builtin_unreachable() /* precondition violation detected! */ > -#else > -# define __glibcxx_constexpr_assert(unevaluated) > -#endif > - > #undef _GLIBCXX_VERBOSE_ASSERT > > // Assert. > diff --git a/libstdc++-v3/include/bits/stl_algobase.h b/libstdc++-v3/include/bits/stl_algobase.h > index 01ca4496dfd..77d0ee7bcf5 100644 > --- a/libstdc++-v3/include/bits/stl_algobase.h > +++ b/libstdc++-v3/include/bits/stl_algobase.h > @@ -318,6 +318,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > { return __it; } > > template<typename _Ite, typename _Seq> > + _GLIBCXX20_CONSTEXPR > _Ite > __niter_base(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, > std::random_access_iterator_tag>&); > @@ -545,6 +546,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER > > template<bool _IsMove, > typename _Ite, typename _Seq, typename _Cat, typename _OI> > + _GLIBCXX20_CONSTEXPR > _OI > __copy_move_a(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>&, > const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>&, > @@ -552,6 +554,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER > > template<bool _IsMove, > typename _II, typename _Ite, typename _Seq, typename _Cat> > + _GLIBCXX20_CONSTEXPR > __gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat> > __copy_move_a(_II, _II, > const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>&); > @@ -559,6 +562,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER > template<bool _IsMove, > typename _IIte, typename _ISeq, typename _ICat, > typename _OIte, typename _OSeq, typename _OCat> > + _GLIBCXX20_CONSTEXPR > ::__gnu_debug::_Safe_iterator<_OIte, _OSeq, _OCat> > __copy_move_a(const ::__gnu_debug::_Safe_iterator<_IIte, _ISeq, _ICat>&, > const ::__gnu_debug::_Safe_iterator<_IIte, _ISeq, _ICat>&, > @@ -812,6 +816,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER > > template<bool _IsMove, > typename _Ite, typename _Seq, typename _Cat, typename _OI> > + _GLIBCXX20_CONSTEXPR > _OI > __copy_move_backward_a( > const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>&, > @@ -820,6 +825,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER > > template<bool _IsMove, > typename _II, typename _Ite, typename _Seq, typename _Cat> > + _GLIBCXX20_CONSTEXPR > __gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat> > __copy_move_backward_a(_II, _II, > const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>&); > @@ -827,6 +833,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER > template<bool _IsMove, > typename _IIte, typename _ISeq, typename _ICat, > typename _OIte, typename _OSeq, typename _OCat> > + _GLIBCXX20_CONSTEXPR > ::__gnu_debug::_Safe_iterator<_OIte, _OSeq, _OCat> > __copy_move_backward_a( > const ::__gnu_debug::_Safe_iterator<_IIte, _ISeq, _ICat>&, > @@ -977,6 +984,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER > { std::__fill_a1(__first, __last, __value); } > > template<typename _Ite, typename _Seq, typename _Cat, typename _Tp> > + _GLIBCXX20_CONSTEXPR > void > __fill_a(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>&, > const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>&, > @@ -1082,6 +1090,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER > > template<typename _Ite, typename _Seq, typename _Cat, typename _Size, > typename _Tp> > + _GLIBCXX20_CONSTEXPR > ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat> > __fill_n_a(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>& __first, > _Size __n, const _Tp& __value, > @@ -1230,18 +1239,21 @@ _GLIBCXX_END_NAMESPACE_CONTAINER > } > > template<typename _II1, typename _Seq1, typename _Cat1, typename _II2> > + _GLIBCXX20_CONSTEXPR > bool > __equal_aux(const ::__gnu_debug::_Safe_iterator<_II1, _Seq1, _Cat1>&, > const ::__gnu_debug::_Safe_iterator<_II1, _Seq1, _Cat1>&, > _II2); > > template<typename _II1, typename _II2, typename _Seq2, typename _Cat2> > + _GLIBCXX20_CONSTEXPR > bool > __equal_aux(_II1, _II1, > const ::__gnu_debug::_Safe_iterator<_II2, _Seq2, _Cat2>&); > > template<typename _II1, typename _Seq1, typename _Cat1, > typename _II2, typename _Seq2, typename _Cat2> > + _GLIBCXX20_CONSTEXPR > bool > __equal_aux(const ::__gnu_debug::_Safe_iterator<_II1, _Seq1, _Cat1>&, > const ::__gnu_debug::_Safe_iterator<_II1, _Seq1, _Cat1>&, > @@ -1430,6 +1442,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER > > template<typename _Iter1, typename _Seq1, typename _Cat1, > typename _II2> > + _GLIBCXX20_CONSTEXPR > bool > __lexicographical_compare_aux( > const ::__gnu_debug::_Safe_iterator<_Iter1, _Seq1, _Cat1>&, > @@ -1438,6 +1451,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER > > template<typename _II1, > typename _Iter2, typename _Seq2, typename _Cat2> > + _GLIBCXX20_CONSTEXPR > bool > __lexicographical_compare_aux( > _II1, _II1, > @@ -1446,6 +1460,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER > > template<typename _Iter1, typename _Seq1, typename _Cat1, > typename _Iter2, typename _Seq2, typename _Cat2> > + _GLIBCXX20_CONSTEXPR > bool > __lexicographical_compare_aux( > const ::__gnu_debug::_Safe_iterator<_Iter1, _Seq1, _Cat1>&, > diff --git a/libstdc++-v3/include/debug/helper_functions.h b/libstdc++-v3/include/debug/helper_functions.h > index 052b36b484c..4b76cb00f9a 100644 > --- a/libstdc++-v3/include/debug/helper_functions.h > +++ b/libstdc++-v3/include/debug/helper_functions.h > @@ -324,6 +324,7 @@ namespace __gnu_debug > > /* Remove debug mode safe iterator layer, if any. */ > template<typename _Iterator> > + _GLIBCXX_CONSTEXPR > inline _Iterator > __unsafe(_Iterator __it) > { return __it; } > diff --git a/libstdc++-v3/include/debug/macros.h b/libstdc++-v3/include/debug/macros.h > index 0fef0a006fc..4a3d0f2ea84 100644 > --- a/libstdc++-v3/include/debug/macros.h > +++ b/libstdc++-v3/include/debug/macros.h > @@ -38,15 +38,12 @@ > * the user error and where the error is reported. > * > */ > -#define _GLIBCXX_DEBUG_VERIFY_COND_AT(_Cond,_ErrMsg,_File,_Line,_Func) \ > - if (__builtin_expect(!bool(_Cond), false)) \ > - __gnu_debug::_Error_formatter::_S_at(_File, _Line, _Func) \ > - ._ErrMsg._M_error() > > #define _GLIBCXX_DEBUG_VERIFY_AT_F(_Cond,_ErrMsg,_File,_Line,_Func) \ > do { \ > - __glibcxx_constexpr_assert(_Cond); \ > - _GLIBCXX_DEBUG_VERIFY_COND_AT(_Cond,_ErrMsg,_File,_Line,_Func); \ > + if (__builtin_expect(!bool(_Cond), false)) \ > + __gnu_debug::_Error_formatter::_S_at(_File, _Line, _Func) \ > + ._ErrMsg._M_error(); \ > } while (false) > > #define _GLIBCXX_DEBUG_VERIFY_AT(_Cond,_ErrMsg,_File,_Line) \ > diff --git a/libstdc++-v3/include/debug/safe_base.h b/libstdc++-v3/include/debug/safe_base.h > index 1dfa9f68b65..d9c17b52b48 100644 > --- a/libstdc++-v3/include/debug/safe_base.h > +++ b/libstdc++-v3/include/debug/safe_base.h > @@ -75,6 +75,7 @@ namespace __gnu_debug > > protected: > /** Initializes the iterator and makes it singular. */ > + _GLIBCXX20_CONSTEXPR > _Safe_iterator_base() > : _M_sequence(0), _M_version(0), _M_prior(0), _M_next(0) > { } > @@ -86,18 +87,31 @@ namespace __gnu_debug > * singular. Otherwise, the iterator will reference @p __seq and > * be nonsingular. > */ > + _GLIBCXX20_CONSTEXPR > _Safe_iterator_base(const _Safe_sequence_base* __seq, bool __constant) > : _M_sequence(0), _M_version(0), _M_prior(0), _M_next(0) > - { this->_M_attach(const_cast<_Safe_sequence_base*>(__seq), __constant); } > + { > + if (!std::__is_constant_evaluated()) > + this->_M_attach(const_cast<_Safe_sequence_base*>(__seq), __constant); > + } > > /** Initializes the iterator to reference the same sequence that > @p __x does. @p __constant is true if this is a constant > iterator, and false if it is mutable. */ > + _GLIBCXX20_CONSTEXPR > _Safe_iterator_base(const _Safe_iterator_base& __x, bool __constant) > : _M_sequence(0), _M_version(0), _M_prior(0), _M_next(0) > - { this->_M_attach(__x._M_sequence, __constant); } > + { > + if (!std::__is_constant_evaluated()) > + this->_M_attach(__x._M_sequence, __constant); > + } > > - ~_Safe_iterator_base() { this->_M_detach(); } > + _GLIBCXX20_CONSTEXPR > + ~_Safe_iterator_base() > + { > + if (!std::__is_constant_evaluated()) > + this->_M_detach(); > + } > > /** For use in _Safe_iterator. */ > __gnu_cxx::__mutex& > @@ -201,24 +215,34 @@ namespace __gnu_debug > > protected: > // Initialize with a version number of 1 and no iterators > + _GLIBCXX20_CONSTEXPR > _Safe_sequence_base() _GLIBCXX_NOEXCEPT > : _M_iterators(0), _M_const_iterators(0), _M_version(1) > { } > > #if __cplusplus >= 201103L > + _GLIBCXX20_CONSTEXPR > _Safe_sequence_base(const _Safe_sequence_base&) noexcept > : _Safe_sequence_base() { } > > // Move constructor swap iterators. > + _GLIBCXX20_CONSTEXPR > _Safe_sequence_base(_Safe_sequence_base&& __seq) noexcept > : _Safe_sequence_base() > - { _M_swap(__seq); } > + { > + if (!std::__is_constant_evaluated()) > + _M_swap(__seq); > + } > #endif > > /** Notify all iterators that reference this sequence that the > sequence is being destroyed. */ > + _GLIBCXX20_CONSTEXPR > ~_Safe_sequence_base() > - { this->_M_detach_all(); } > + { > + if (!std::__is_constant_evaluated()) > + this->_M_detach_all(); > + } > > /** Detach all iterators, leaving them singular. */ > void > @@ -244,6 +268,7 @@ namespace __gnu_debug > * operation is complete all iterators that originally referenced > * one container now reference the other container. > */ > + _GLIBCXX20_CONSTEXPR > void > _M_swap(_Safe_sequence_base& __x) _GLIBCXX_USE_NOEXCEPT; With -Wsystem-headers on some ranges tests I get: /gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/debug/safe_base.h:273:5: warning: inline function ‘constexpr void __gnu_debug::_Safe_sequence_base::_M_swap(__gnu_debug::_Safe_sequence_base&)’ used but never defined 273 | _M_swap(_Safe_sequence_base& __x) _GLIBCXX_USE_NOEXCEPT; | ^~~~~~~ > > diff --git a/libstdc++-v3/include/debug/safe_container.h b/libstdc++-v3/include/debug/safe_container.h > index 0d8f64740b0..636156af9f5 100644 > --- a/libstdc++-v3/include/debug/safe_container.h > +++ b/libstdc++-v3/include/debug/safe_container.h > @@ -43,6 +43,7 @@ namespace __gnu_debug > { > typedef _SafeBase<_SafeContainer> _Base; > > + _GLIBCXX20_CONSTEXPR > _SafeContainer& > _M_cont() _GLIBCXX_NOEXCEPT > { return *static_cast<_SafeContainer*>(this); } > @@ -54,20 +55,23 @@ namespace __gnu_debug > _Safe_container(_Safe_container&&) = default; > > private: > + _GLIBCXX20_CONSTEXPR > _Safe_container(_Safe_container&& __x, const _Alloc&, std::true_type) > : _Safe_container(std::move(__x)) > { } > > + _GLIBCXX20_CONSTEXPR > _Safe_container(_Safe_container&& __x, const _Alloc& __a, std::false_type) > : _Safe_container() > { > if (__x._M_cont().get_allocator() == __a) > _Base::_M_swap(__x); > - else > + else if (!std::__is_constant_evaluated()) > __x._M_invalidate_all(); > } > > protected: > + _GLIBCXX20_CONSTEXPR > _Safe_container(_Safe_container&& __x, const _Alloc& __a) > : _Safe_container(std::move(__x), __a, > typename std::allocator_traits<_Alloc>::is_always_equal{}) > @@ -75,17 +79,23 @@ namespace __gnu_debug > #endif > > // Copy assignment invalidate all iterators. > + _GLIBCXX20_CONSTEXPR > _Safe_container& > operator=(const _Safe_container&) _GLIBCXX_NOEXCEPT > { > - this->_M_invalidate_all(); > + if (!std::__is_constant_evaluated()) > + this->_M_invalidate_all(); > return *this; > } > > #if __cplusplus >= 201103L > + _GLIBCXX20_CONSTEXPR > _Safe_container& > operator=(_Safe_container&& __x) noexcept > { > + if (std::__is_constant_evaluated()) > + return *this; > + > if (std::__addressof(__x) == this) > { > // Standard containers have a valid but unspecified value after > @@ -113,6 +123,7 @@ namespace __gnu_debug > return *this; > } > > + _GLIBCXX20_CONSTEXPR > void > _M_swap(_Safe_container& __x) noexcept > { > diff --git a/libstdc++-v3/include/debug/safe_iterator.h b/libstdc++-v3/include/debug/safe_iterator.h > index 693192b3ea9..26f008982f8 100644 > --- a/libstdc++-v3/include/debug/safe_iterator.h > +++ b/libstdc++-v3/include/debug/safe_iterator.h > @@ -40,6 +40,7 @@ > #endif > > #define _GLIBCXX_DEBUG_VERIFY_OPERANDS(_Lhs, _Rhs, _BadMsgId, _DiffMsgId) \ > + if (!std::__is_constant_evaluated()) { \ > _GLIBCXX_DEBUG_VERIFY((!_Lhs._M_singular() && !_Rhs._M_singular()) \ > || (_Lhs._M_value_initialized() \ > && _Rhs._M_value_initialized()), \ > @@ -49,7 +50,8 @@ > _GLIBCXX_DEBUG_VERIFY(_Lhs._M_can_compare(_Rhs), \ > _M_message(_DiffMsgId) \ > ._M_iterator(_Lhs, #_Lhs) \ > - ._M_iterator(_Rhs, #_Rhs)) > + ._M_iterator(_Rhs, #_Rhs)); \ > + } > > #define _GLIBCXX_DEBUG_VERIFY_EQ_OPERANDS(_Lhs, _Rhs) \ > _GLIBCXX_DEBUG_VERIFY_OPERANDS(_Lhs, _Rhs, __msg_iter_compare_bad, \ > @@ -131,9 +133,13 @@ namespace __gnu_debug > > struct _Unchecked { }; > > + _GLIBCXX20_CONSTEXPR > _Safe_iterator(const _Safe_iterator& __x, _Unchecked) _GLIBCXX_NOEXCEPT > : _Iter_base(__x.base()), _Safe_base() > - { _M_attach(__x._M_sequence); } > + { > + if (!std::__is_constant_evaluated()) > + _M_attach(__x._M_sequence); > + } > > public: > typedef _Iterator iterator_type; > @@ -148,6 +154,7 @@ namespace __gnu_debug > #endif > > /// @post the iterator is singular and unattached > + _GLIBCXX20_CONSTEXPR > _Safe_iterator() _GLIBCXX_NOEXCEPT : _Iter_base() { } > > /** > @@ -157,6 +164,7 @@ namespace __gnu_debug > * @pre @p seq is not NULL > * @post this is not singular > */ > + _GLIBCXX20_CONSTEXPR > _Safe_iterator(_Iterator __i, const _Safe_sequence_base* __seq) > _GLIBCXX_NOEXCEPT > : _Iter_base(__i), _Safe_base(__seq, _S_constant()) > @@ -165,9 +173,13 @@ namespace __gnu_debug > /** > * @brief Copy construction. > */ > + _GLIBCXX20_CONSTEXPR > _Safe_iterator(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT > : _Iter_base(__x.base()), _Safe_base() > { > + if (std::__is_constant_evaluated()) > + return; > + > // _GLIBCXX_RESOLVE_LIB_DEFECTS > // DR 408. Is vector<reverse_iterator<char*> > forbidden? > _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() > @@ -183,9 +195,16 @@ namespace __gnu_debug > * @brief Move construction. > * @post __x is singular and unattached > */ > + _GLIBCXX20_CONSTEXPR > _Safe_iterator(_Safe_iterator&& __x) noexcept > : _Iter_base() > { > + if (std::__is_constant_evaluated()) > + { > + base() = __x.base(); > + return; > + } > + > _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() > || __x._M_value_initialized(), > _M_message(__msg_init_copy_singular) > @@ -203,6 +222,7 @@ namespace __gnu_debug > * constant iterator. > */ > template<typename _MutableIterator> > + _GLIBCXX20_CONSTEXPR > _Safe_iterator( > const _Safe_iterator<_MutableIterator, _Sequence, > typename __gnu_cxx::__enable_if<_IsConstant::__value && > @@ -211,6 +231,9 @@ namespace __gnu_debug > _GLIBCXX_NOEXCEPT > : _Iter_base(__x.base()) > { > + if (std::__is_constant_evaluated()) > + return; > + > // _GLIBCXX_RESOLVE_LIB_DEFECTS > // DR 408. Is vector<reverse_iterator<char*> > forbidden? > _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() > @@ -224,9 +247,16 @@ namespace __gnu_debug > /** > * @brief Copy assignment. > */ > + _GLIBCXX20_CONSTEXPR > _Safe_iterator& > operator=(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT > { > + if (std::__is_constant_evaluated()) > + { > + base() = __x.base(); > + return *this; > + } > + > // _GLIBCXX_RESOLVE_LIB_DEFECTS > // DR 408. Is vector<reverse_iterator<char*> > forbidden? > _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() > @@ -256,9 +286,16 @@ namespace __gnu_debug > * @brief Move assignment. > * @post __x is singular and unattached > */ > + _GLIBCXX20_CONSTEXPR > _Safe_iterator& > operator=(_Safe_iterator&& __x) noexcept > { > + if (std::__is_constant_evaluated()) > + { > + base() = __x.base(); > + return *this; > + } > + > _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() > || __x._M_value_initialized(), > _M_message(__msg_copy_singular) > @@ -292,12 +329,16 @@ namespace __gnu_debug > * @pre iterator is dereferenceable > */ > _GLIBCXX_NODISCARD > + _GLIBCXX20_CONSTEXPR > reference > operator*() const _GLIBCXX_NOEXCEPT > { > - _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(), > - _M_message(__msg_bad_deref) > - ._M_iterator(*this, "this")); > + if (!std::__is_constant_evaluated()) > + { > + _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(), > + _M_message(__msg_bad_deref) > + ._M_iterator(*this, "this")); > + } > return *base(); > } > > @@ -306,12 +347,16 @@ namespace __gnu_debug > * @pre iterator is dereferenceable > */ > _GLIBCXX_NODISCARD > + _GLIBCXX20_CONSTEXPR > pointer > operator->() const _GLIBCXX_NOEXCEPT > { > - _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(), > - _M_message(__msg_bad_deref) > - ._M_iterator(*this, "this")); > + if (!std::__is_constant_evaluated()) > + { > + _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(), > + _M_message(__msg_bad_deref) > + ._M_iterator(*this, "this")); > + } > return base().operator->(); > } > > @@ -320,9 +365,16 @@ namespace __gnu_debug > * @brief Iterator preincrement > * @pre iterator is incrementable > */ > + _GLIBCXX20_CONSTEXPR > _Safe_iterator& > operator++() _GLIBCXX_NOEXCEPT > { > + if (std::__is_constant_evaluated()) > + { > + ++base(); > + return *this; > + } > + > _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(), > _M_message(__msg_bad_inc) > ._M_iterator(*this, "this")); > @@ -335,12 +387,16 @@ namespace __gnu_debug > * @brief Iterator postincrement > * @pre iterator is incrementable > */ > + _GLIBCXX20_CONSTEXPR > _Safe_iterator > operator++(int) _GLIBCXX_NOEXCEPT > { > - _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(), > - _M_message(__msg_bad_inc) > - ._M_iterator(*this, "this")); > + if (!std::__is_constant_evaluated()) > + { > + _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(), > + _M_message(__msg_bad_inc) > + ._M_iterator(*this, "this")); > + } > _Safe_iterator __ret(*this, _Unchecked()); > ++*this; > return __ret; > @@ -356,9 +412,11 @@ namespace __gnu_debug > /** > * @brief Return the underlying iterator > */ > + _GLIBCXX20_CONSTEXPR > _Iterator& > base() _GLIBCXX_NOEXCEPT { return *this; } > > + _GLIBCXX20_CONSTEXPR > const _Iterator& > base() const _GLIBCXX_NOEXCEPT { return *this; } > > @@ -366,6 +424,7 @@ namespace __gnu_debug > * @brief Conversion to underlying non-debug iterator to allow > * better interaction with non-debug containers. > */ > + _GLIBCXX20_CONSTEXPR > operator _Iterator() const _GLIBCXX_NOEXCEPT { return *this; } > > /** Attach iterator to the given sequence. */ > @@ -440,6 +499,7 @@ namespace __gnu_debug > _M_get_distance_to_end() const; > > /// Is this iterator equal to the sequence's begin() iterator? > + _GLIBCXX20_CONSTEXPR > bool > _M_is_begin() const > { return base() == _M_get_sequence()->_M_base().begin(); } > @@ -466,6 +526,7 @@ namespace __gnu_debug > typedef _Safe_iterator<_Iterator, _Sequence, iterator_category> _Self; > > _GLIBCXX_NODISCARD > + _GLIBCXX20_CONSTEXPR > friend bool > operator==(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT > { > @@ -475,6 +536,7 @@ namespace __gnu_debug > > template<typename _IteR> > _GLIBCXX_NODISCARD > + _GLIBCXX20_CONSTEXPR > friend bool > operator==(const _Self& __lhs, > const _Safe_iterator<_IteR, _Sequence, iterator_category>& __rhs) > @@ -518,6 +580,7 @@ namespace __gnu_debug > > typedef typename _Safe_base::_Unchecked _Unchecked; > > + _GLIBCXX20_CONSTEXPR > _Safe_iterator(const _Safe_iterator& __x, > _Unchecked __unchecked) _GLIBCXX_NOEXCEPT > : _Safe_base(__x, __unchecked) > @@ -525,6 +588,7 @@ namespace __gnu_debug > > public: > /// @post the iterator is singular and unattached > + _GLIBCXX20_CONSTEXPR > _Safe_iterator() _GLIBCXX_NOEXCEPT { } > > /** > @@ -534,6 +598,7 @@ namespace __gnu_debug > * @pre @p seq is not NULL > * @post this is not singular > */ > + _GLIBCXX20_CONSTEXPR > _Safe_iterator(_Iterator __i, const _Safe_sequence_base* __seq) > _GLIBCXX_NOEXCEPT > : _Safe_base(__i, __seq) > @@ -542,12 +607,14 @@ namespace __gnu_debug > /** > * @brief Copy construction. > */ > + _GLIBCXX20_CONSTEXPR > _Safe_iterator(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT > : _Safe_base(__x) > { } > > #if __cplusplus >= 201103L > /** @brief Move construction. */ > + _GLIBCXX20_CONSTEXPR > _Safe_iterator(_Safe_iterator&&) = default; > #endif > > @@ -556,6 +623,7 @@ namespace __gnu_debug > * constant iterator. > */ > template<typename _MutableIterator> > + _GLIBCXX20_CONSTEXPR > _Safe_iterator( > const _Safe_iterator<_MutableIterator, _Sequence, > typename __gnu_cxx::__enable_if<_Safe_base::_IsConstant::__value && > @@ -588,6 +656,7 @@ namespace __gnu_debug > * @brief Iterator preincrement > * @pre iterator is incrementable > */ > + _GLIBCXX20_CONSTEXPR > _Safe_iterator& > operator++() _GLIBCXX_NOEXCEPT > { > @@ -615,9 +684,16 @@ namespace __gnu_debug > * @brief Iterator predecrement > * @pre iterator is decrementable > */ > + _GLIBCXX20_CONSTEXPR > _Safe_iterator& > operator--() _GLIBCXX_NOEXCEPT > { > + if (std::__is_constant_evaluated()) > + { > + --this->base(); > + return *this; > + } > + > _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(), > _M_message(__msg_bad_dec) > ._M_iterator(*this, "this")); > @@ -663,6 +739,8 @@ namespace __gnu_debug > std::random_access_iterator_tag> _OtherSelf; > > typedef typename _Safe_base::_Unchecked _Unchecked; > + > + _GLIBCXX20_CONSTEXPR > _Safe_iterator(const _Safe_iterator& __x, > _Unchecked __unchecked) _GLIBCXX_NOEXCEPT > : _Safe_base(__x, __unchecked) > @@ -673,6 +751,7 @@ namespace __gnu_debug > typedef typename _Safe_base::reference reference; > > /// @post the iterator is singular and unattached > + _GLIBCXX20_CONSTEXPR > _Safe_iterator() _GLIBCXX_NOEXCEPT { } > > /** > @@ -682,6 +761,7 @@ namespace __gnu_debug > * @pre @p seq is not NULL > * @post this is not singular > */ > + _GLIBCXX20_CONSTEXPR > _Safe_iterator(_Iterator __i, const _Safe_sequence_base* __seq) > _GLIBCXX_NOEXCEPT > : _Safe_base(__i, __seq) > @@ -690,6 +770,7 @@ namespace __gnu_debug > /** > * @brief Copy construction. > */ > + _GLIBCXX20_CONSTEXPR > _Safe_iterator(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT > : _Safe_base(__x) > { } > @@ -704,6 +785,7 @@ namespace __gnu_debug > * constant iterator. > */ > template<typename _MutableIterator> > + _GLIBCXX20_CONSTEXPR > _Safe_iterator( > const _Safe_iterator<_MutableIterator, _Sequence, > typename __gnu_cxx::__enable_if<_Safe_base::_IsConstant::__value && > @@ -742,6 +824,7 @@ namespace __gnu_debug > * @brief Iterator preincrement > * @pre iterator is incrementable > */ > + _GLIBCXX20_CONSTEXPR > _Safe_iterator& > operator++() _GLIBCXX_NOEXCEPT > { > @@ -753,12 +836,16 @@ namespace __gnu_debug > * @brief Iterator postincrement > * @pre iterator is incrementable > */ > + _GLIBCXX20_CONSTEXPR > _Safe_iterator > operator++(int) _GLIBCXX_NOEXCEPT > { > - _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(), > - _M_message(__msg_bad_inc) > - ._M_iterator(*this, "this")); > + if (!std::__is_constant_evaluated()) > + { > + _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(), > + _M_message(__msg_bad_inc) > + ._M_iterator(*this, "this")); > + } > _Safe_iterator __ret(*this, _Unchecked()); > ++*this; > return __ret; > @@ -769,6 +856,7 @@ namespace __gnu_debug > * @brief Iterator predecrement > * @pre iterator is decrementable > */ > + _GLIBCXX20_CONSTEXPR > _Safe_iterator& > operator--() _GLIBCXX_NOEXCEPT > { > @@ -780,12 +868,16 @@ namespace __gnu_debug > * @brief Iterator postdecrement > * @pre iterator is decrementable > */ > + _GLIBCXX20_CONSTEXPR > _Safe_iterator > operator--(int) _GLIBCXX_NOEXCEPT > { > - _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(), > - _M_message(__msg_bad_dec) > - ._M_iterator(*this, "this")); > + if (!std::__is_constant_evaluated()) > + { > + _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(), > + _M_message(__msg_bad_dec) > + ._M_iterator(*this, "this")); > + } > _Safe_iterator __ret(*this, _Unchecked()); > --*this; > return __ret; > @@ -793,19 +885,30 @@ namespace __gnu_debug > > // ------ Random access iterator requirements ------ > _GLIBCXX_NODISCARD > + _GLIBCXX20_CONSTEXPR > reference > operator[](difference_type __n) const _GLIBCXX_NOEXCEPT > { > - _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n) > - && this->_M_can_advance(__n + 1), > - _M_message(__msg_iter_subscript_oob) > - ._M_iterator(*this)._M_integer(__n)); > + if (!std::__is_constant_evaluated()) > + { > + _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n) > + && this->_M_can_advance(__n + 1), > + _M_message(__msg_iter_subscript_oob) > + ._M_iterator(*this)._M_integer(__n)); > + } > return this->base()[__n]; > } > > + _GLIBCXX20_CONSTEXPR > _Safe_iterator& > operator+=(difference_type __n) _GLIBCXX_NOEXCEPT > { > + if (std::__is_constant_evaluated()) > + { > + this->base() += __n; > + return *this; > + } > + > _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n), > _M_message(__msg_advance_oob) > ._M_iterator(*this)._M_integer(__n)); > @@ -814,9 +917,16 @@ namespace __gnu_debug > return *this; > } > > + _GLIBCXX20_CONSTEXPR > _Safe_iterator& > operator-=(difference_type __n) _GLIBCXX_NOEXCEPT > { > + if (std::__is_constant_evaluated()) > + { > + this->base() -= __n; > + return *this; > + } > + > _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(-__n), > _M_message(__msg_retreat_oob) > ._M_iterator(*this)._M_integer(__n)); > @@ -827,6 +937,7 @@ namespace __gnu_debug > > #if __cpp_lib_three_way_comparison > [[nodiscard]] > + _GLIBCXX20_CONSTEXPR > friend auto > operator<=>(const _Self& __lhs, const _Self& __rhs) noexcept > { > @@ -835,6 +946,7 @@ namespace __gnu_debug > } > > [[nodiscard]] > + _GLIBCXX20_CONSTEXPR > friend auto > operator<=>(const _Self& __lhs, const _OtherSelf& __rhs) noexcept > { > @@ -912,6 +1024,7 @@ namespace __gnu_debug > // operators but also operator- must accept mixed iterator/const_iterator > // parameters. > _GLIBCXX_NODISCARD > + _GLIBCXX20_CONSTEXPR > friend difference_type > operator-(const _Self& __lhs, const _OtherSelf& __rhs) _GLIBCXX_NOEXCEPT > { > @@ -920,6 +1033,7 @@ namespace __gnu_debug > } > > _GLIBCXX_NODISCARD > + _GLIBCXX20_CONSTEXPR > friend difference_type > operator-(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT > { > @@ -928,32 +1042,44 @@ namespace __gnu_debug > } > > _GLIBCXX_NODISCARD > + _GLIBCXX20_CONSTEXPR > friend _Self > operator+(const _Self& __x, difference_type __n) _GLIBCXX_NOEXCEPT > { > - _GLIBCXX_DEBUG_VERIFY(__x._M_can_advance(__n), > - _M_message(__msg_advance_oob) > - ._M_iterator(__x)._M_integer(__n)); > + if (!std::__is_constant_evaluated()) > + { > + _GLIBCXX_DEBUG_VERIFY(__x._M_can_advance(__n), > + _M_message(__msg_advance_oob) > + ._M_iterator(__x)._M_integer(__n)); > + } > return _Safe_iterator(__x.base() + __n, __x._M_sequence); > } > > _GLIBCXX_NODISCARD > + _GLIBCXX20_CONSTEXPR > friend _Self > operator+(difference_type __n, const _Self& __x) _GLIBCXX_NOEXCEPT > { > - _GLIBCXX_DEBUG_VERIFY(__x._M_can_advance(__n), > - _M_message(__msg_advance_oob) > - ._M_iterator(__x)._M_integer(__n)); > + if (!std::__is_constant_evaluated()) > + { > + _GLIBCXX_DEBUG_VERIFY(__x._M_can_advance(__n), > + _M_message(__msg_advance_oob) > + ._M_iterator(__x)._M_integer(__n)); > + } > return _Safe_iterator(__n + __x.base(), __x._M_sequence); > } > > _GLIBCXX_NODISCARD > + _GLIBCXX20_CONSTEXPR > friend _Self > operator-(const _Self& __x, difference_type __n) _GLIBCXX_NOEXCEPT > { > - _GLIBCXX_DEBUG_VERIFY(__x._M_can_advance(-__n), > - _M_message(__msg_retreat_oob) > - ._M_iterator(__x)._M_integer(__n)); > + if (!std::__is_constant_evaluated()) > + { > + _GLIBCXX_DEBUG_VERIFY(__x._M_can_advance(-__n), > + _M_message(__msg_retreat_oob) > + ._M_iterator(__x)._M_integer(__n)); > + } > return _Safe_iterator(__x.base() - __n, __x._M_sequence); > } > }; > diff --git a/libstdc++-v3/include/debug/safe_iterator.tcc b/libstdc++-v3/include/debug/safe_iterator.tcc > index 170229ad2f1..0bb3dd017b9 100644 > --- a/libstdc++-v3/include/debug/safe_iterator.tcc > +++ b/libstdc++-v3/include/debug/safe_iterator.tcc > @@ -236,6 +236,7 @@ namespace std _GLIBCXX_VISIBILITY(default) > _GLIBCXX_BEGIN_NAMESPACE_VERSION > > template<typename _Ite, typename _Seq> > + _GLIBCXX20_CONSTEXPR > _Ite > __niter_base(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, > std::random_access_iterator_tag>& __it) > @@ -243,6 +244,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > template<bool _IsMove, > typename _Ite, typename _Seq, typename _Cat, typename _OI> > + _GLIBCXX20_CONSTEXPR > _OI > __copy_move_a( > const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>& __first, > @@ -262,6 +264,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > template<bool _IsMove, > typename _II, typename _Ite, typename _Seq, typename _Cat> > + _GLIBCXX20_CONSTEXPR > __gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat> > __copy_move_a(_II __first, _II __last, > const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>& __result) > @@ -282,6 +285,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > template<bool _IsMove, > typename _IIte, typename _ISeq, typename _ICat, > typename _OIte, typename _OSeq, typename _OCat> > + _GLIBCXX20_CONSTEXPR > ::__gnu_debug::_Safe_iterator<_OIte, _OSeq, _OCat> > __copy_move_a( > const ::__gnu_debug::_Safe_iterator<_IIte, _ISeq, _ICat>& __first, > @@ -310,6 +314,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > template<bool _IsMove, > typename _Ite, typename _Seq, typename _Cat, typename _OI> > + _GLIBCXX20_CONSTEXPR > _OI > __copy_move_backward_a( > const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>& __first, > @@ -329,6 +334,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > template<bool _IsMove, > typename _II, typename _Ite, typename _Seq, typename _Cat> > + _GLIBCXX20_CONSTEXPR > __gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat> > __copy_move_backward_a(_II __first, _II __last, > const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>& __result) > @@ -350,6 +356,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > template<bool _IsMove, > typename _IIte, typename _ISeq, typename _ICat, > typename _OIte, typename _OSeq, typename _OCat> > + _GLIBCXX20_CONSTEXPR > ::__gnu_debug::_Safe_iterator<_OIte, _OSeq, _OCat> > __copy_move_backward_a( > const ::__gnu_debug::_Safe_iterator<_IIte, _ISeq, _ICat>& __first, > @@ -377,6 +384,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > } > > template<typename _Ite, typename _Seq, typename _Cat, typename _Tp> > + _GLIBCXX20_CONSTEXPR > void > __fill_a(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>& __first, > const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>& __last, > @@ -393,6 +401,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > template<typename _Ite, typename _Seq, typename _Cat, typename _Size, > typename _Tp> > + _GLIBCXX20_CONSTEXPR > ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat> > __fill_n_a(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>& __first, > _Size __n, const _Tp& __value, > @@ -415,6 +424,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > } > > template<typename _II1, typename _Seq1, typename _Cat1, typename _II2> > + _GLIBCXX20_CONSTEXPR > bool > __equal_aux( > const ::__gnu_debug::_Safe_iterator<_II1, _Seq1, _Cat1>& __first1, > @@ -432,6 +442,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > } > > template<typename _II1, typename _II2, typename _Seq2, typename _Cat2> > + _GLIBCXX20_CONSTEXPR > bool > __equal_aux(_II1 __first1, _II1 __last1, > const ::__gnu_debug::_Safe_iterator<_II2, _Seq2, _Cat2>& __first2) > @@ -449,6 +460,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > template<typename _II1, typename _Seq1, typename _Cat1, > typename _II2, typename _Seq2, typename _Cat2> > + _GLIBCXX20_CONSTEXPR > bool > __equal_aux( > const ::__gnu_debug::_Safe_iterator<_II1, _Seq1, _Cat1>& __first1, > @@ -473,6 +485,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > template<typename _Ite1, typename _Seq1, typename _Cat1, > typename _II2> > + _GLIBCXX20_CONSTEXPR > bool > __lexicographical_compare_aux( > const ::__gnu_debug::_Safe_iterator<_Ite1, _Seq1, _Cat1>& __first1, > @@ -493,6 +506,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > template<typename _II1, > typename _Ite2, typename _Seq2, typename _Cat2> > + _GLIBCXX20_CONSTEXPR > bool > __lexicographical_compare_aux( > _II1 __first1, _II1 __last1, > @@ -513,6 +527,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > template<typename _Ite1, typename _Seq1, typename _Cat1, > typename _Ite2, typename _Seq2, typename _Cat2> > + _GLIBCXX20_CONSTEXPR > bool > __lexicographical_compare_aux( > const ::__gnu_debug::_Safe_iterator<_Ite1, _Seq1, _Cat1>& __first1, > diff --git a/libstdc++-v3/include/debug/vector b/libstdc++-v3/include/debug/vector > index ed462caf936..124ae6da1c1 100644 > --- a/libstdc++-v3/include/debug/vector > +++ b/libstdc++-v3/include/debug/vector > @@ -55,22 +55,27 @@ namespace __gnu_debug > { > typedef typename _BaseSequence::size_type size_type; > > + _GLIBCXX20_CONSTEXPR > const _SafeSequence& > _M_seq() const { return *static_cast<const _SafeSequence*>(this); } > > protected: > + _GLIBCXX20_CONSTEXPR > _Safe_vector() _GLIBCXX_NOEXCEPT > : _M_guaranteed_capacity(0) > { _M_update_guaranteed_capacity(); } > > + _GLIBCXX20_CONSTEXPR > _Safe_vector(const _Safe_vector&) _GLIBCXX_NOEXCEPT > : _M_guaranteed_capacity(0) > { _M_update_guaranteed_capacity(); } > > + _GLIBCXX20_CONSTEXPR > _Safe_vector(size_type __n) _GLIBCXX_NOEXCEPT > : _M_guaranteed_capacity(__n) > { } > > + _GLIBCXX20_CONSTEXPR > _Safe_vector& > operator=(const _Safe_vector&) _GLIBCXX_NOEXCEPT > { > @@ -79,10 +84,12 @@ namespace __gnu_debug > } > > #if __cplusplus >= 201103L > + _GLIBCXX20_CONSTEXPR > _Safe_vector(_Safe_vector&& __x) noexcept > : _Safe_vector() > { __x._M_guaranteed_capacity = 0; } > > + _GLIBCXX20_CONSTEXPR > _Safe_vector& > operator=(_Safe_vector&& __x) noexcept > { > @@ -98,6 +105,7 @@ namespace __gnu_debug > _M_requires_reallocation(size_type __elements) const _GLIBCXX_NOEXCEPT > { return __elements > _M_seq().capacity(); } > > + _GLIBCXX20_CONSTEXPR > void > _M_update_guaranteed_capacity() _GLIBCXX_NOEXCEPT > { > @@ -172,15 +180,18 @@ namespace __debug > vector() = default; > #endif > > + _GLIBCXX20_CONSTEXPR > explicit > vector(const _Allocator& __a) _GLIBCXX_NOEXCEPT > : _Base(__a) { } > > #if __cplusplus >= 201103L > + _GLIBCXX20_CONSTEXPR > explicit > vector(size_type __n, const _Allocator& __a = _Allocator()) > : _Base(__n, __a), _Safe_vector(__n) { } > > + _GLIBCXX20_CONSTEXPR > vector(size_type __n, const __type_identity_t<_Tp>& __value, > const _Allocator& __a = _Allocator()) > : _Base(__n, __value, __a) { } > @@ -197,10 +208,11 @@ namespace __debug > #else > template<class _InputIterator> > #endif > + _GLIBCXX20_CONSTEXPR > vector(_InputIterator __first, _InputIterator __last, > const _Allocator& __a = _Allocator()) > - : _Base(__gnu_debug::__base( > - __glibcxx_check_valid_constructor_range(__first, __last)), > + : _Base(__gnu_debug::__base(std::__is_constant_evaluated() ? __first > + : __glibcxx_check_valid_constructor_range(__first, __last)), > __gnu_debug::__base(__last), __a) { } > > #if __cplusplus < 201103L > @@ -212,9 +224,11 @@ namespace __debug > vector(const vector&) = default; > vector(vector&&) = default; > > + _GLIBCXX20_CONSTEXPR > vector(const vector& __x, const __type_identity_t<allocator_type>& __a) > : _Base(__x, __a) { } > > + _GLIBCXX20_CONSTEXPR > vector(vector&& __x, const __type_identity_t<allocator_type>& __a) > noexcept( > std::is_nothrow_constructible<_Base, > @@ -223,6 +237,7 @@ namespace __debug > _Base(std::move(__x), __a), > _Safe_vector(std::move(__x)) { } > > + _GLIBCXX20_CONSTEXPR > vector(initializer_list<value_type> __l, > const allocator_type& __a = allocator_type()) > : _Base(__l, __a) { } > @@ -231,6 +246,7 @@ namespace __debug > #endif > > /// Construction from a normal-mode vector > + _GLIBCXX20_CONSTEXPR > vector(_Base_ref __x) > : _Base(__x._M_ref) { } > > @@ -241,12 +257,16 @@ namespace __debug > vector& > operator=(vector&&) = default; > > + _GLIBCXX20_CONSTEXPR > vector& > operator=(initializer_list<value_type> __l) > { > _Base::operator=(__l); > - this->_M_invalidate_all(); > - this->_M_update_guaranteed_capacity(); > + if (!std::__is_constant_evaluated()) > + { > + this->_M_invalidate_all(); > + this->_M_update_guaranteed_capacity(); > + } > return *this; > } > #endif > @@ -257,9 +277,14 @@ namespace __debug > #else > template<typename _InputIterator> > #endif > + _GLIBCXX20_CONSTEXPR > void > assign(_InputIterator __first, _InputIterator __last) > { > + if (std::__is_constant_evaluated()) > + return _Base::assign(__gnu_debug::__unsafe(__first), > + __gnu_debug::__unsafe(__last)); > + > typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist; > __glibcxx_check_valid_range2(__first, __last, __dist); > > @@ -273,21 +298,29 @@ namespace __debug > this->_M_update_guaranteed_capacity(); > } > > + _GLIBCXX20_CONSTEXPR > void > assign(size_type __n, const _Tp& __u) > { > _Base::assign(__n, __u); > - this->_M_invalidate_all(); > - this->_M_update_guaranteed_capacity(); > + if (!std::__is_constant_evaluated()) > + { > + this->_M_invalidate_all(); > + this->_M_update_guaranteed_capacity(); > + } > } > > #if __cplusplus >= 201103L > + _GLIBCXX20_CONSTEXPR > void > assign(initializer_list<value_type> __l) > { > _Base::assign(__l); > - this->_M_invalidate_all(); > - this->_M_update_guaranteed_capacity(); > + if (!std::__is_constant_evaluated()) > + { > + this->_M_invalidate_all(); > + this->_M_update_guaranteed_capacity(); > + } > } > #endif > > @@ -295,62 +328,74 @@ namespace __debug > > // iterators: > _GLIBCXX_NODISCARD > + _GLIBCXX20_CONSTEXPR > iterator > begin() _GLIBCXX_NOEXCEPT > { return iterator(_Base::begin(), this); } > > _GLIBCXX_NODISCARD > + _GLIBCXX20_CONSTEXPR > const_iterator > begin() const _GLIBCXX_NOEXCEPT > { return const_iterator(_Base::begin(), this); } > > _GLIBCXX_NODISCARD > + _GLIBCXX20_CONSTEXPR > iterator > end() _GLIBCXX_NOEXCEPT > { return iterator(_Base::end(), this); } > > _GLIBCXX_NODISCARD > + _GLIBCXX20_CONSTEXPR > const_iterator > end() const _GLIBCXX_NOEXCEPT > { return const_iterator(_Base::end(), this); } > > _GLIBCXX_NODISCARD > + _GLIBCXX20_CONSTEXPR > reverse_iterator > rbegin() _GLIBCXX_NOEXCEPT > { return reverse_iterator(end()); } > > _GLIBCXX_NODISCARD > + _GLIBCXX20_CONSTEXPR > const_reverse_iterator > rbegin() const _GLIBCXX_NOEXCEPT > { return const_reverse_iterator(end()); } > > _GLIBCXX_NODISCARD > + _GLIBCXX20_CONSTEXPR > reverse_iterator > rend() _GLIBCXX_NOEXCEPT > { return reverse_iterator(begin()); } > > _GLIBCXX_NODISCARD > + _GLIBCXX20_CONSTEXPR > const_reverse_iterator > rend() const _GLIBCXX_NOEXCEPT > { return const_reverse_iterator(begin()); } > > #if __cplusplus >= 201103L > [[__nodiscard__]] > + _GLIBCXX20_CONSTEXPR > const_iterator > cbegin() const noexcept > { return const_iterator(_Base::begin(), this); } > > [[__nodiscard__]] > + _GLIBCXX20_CONSTEXPR > const_iterator > cend() const noexcept > { return const_iterator(_Base::end(), this); } > > [[__nodiscard__]] > + _GLIBCXX20_CONSTEXPR > const_reverse_iterator > crbegin() const noexcept > { return const_reverse_iterator(end()); } > > [[__nodiscard__]] > + _GLIBCXX20_CONSTEXPR > const_reverse_iterator > crend() const noexcept > { return const_reverse_iterator(begin()); } > @@ -361,9 +406,13 @@ namespace __debug > using _Base::max_size; > > #if __cplusplus >= 201103L > + _GLIBCXX20_CONSTEXPR > void > resize(size_type __sz) > { > + if (std::__is_constant_evaluated()) > + return _Base::resize(__sz); > + > bool __realloc = this->_M_requires_reallocation(__sz); > if (__sz < this->size()) > this->_M_invalidate_after_nth(__sz); > @@ -373,9 +422,13 @@ namespace __debug > this->_M_update_guaranteed_capacity(); > } > > + _GLIBCXX20_CONSTEXPR > void > resize(size_type __sz, const _Tp& __c) > { > + if (std::__is_constant_evaluated()) > + return _Base::resize(__sz, __c); > + > bool __realloc = this->_M_requires_reallocation(__sz); > if (__sz < this->size()) > this->_M_invalidate_after_nth(__sz); > @@ -399,9 +452,13 @@ namespace __debug > #endif > > #if __cplusplus >= 201103L > + _GLIBCXX20_CONSTEXPR > void > shrink_to_fit() > { > + if (std::__is_constant_evaluated()) > + return _Base::shrink_to_fit(); > + > if (_Base::_M_shrink_to_fit()) > { > this->_M_guaranteed_capacity = _Base::capacity(); > @@ -411,9 +468,13 @@ namespace __debug > #endif > > _GLIBCXX_NODISCARD > + _GLIBCXX20_CONSTEXPR > size_type > capacity() const _GLIBCXX_NOEXCEPT > { > + if (std::__is_constant_evaluated()) > + return _Base::capacity(); > + > #ifdef _GLIBCXX_DEBUG_PEDANTIC > return this->_M_guaranteed_capacity; > #else > @@ -423,9 +484,13 @@ namespace __debug > > using _Base::empty; > > + _GLIBCXX20_CONSTEXPR > void > reserve(size_type __n) > { > + if (std::__is_constant_evaluated()) > + return _Base::reserve(__n); > + > bool __realloc = this->_M_requires_reallocation(__n); > _Base::reserve(__n); > if (__n > this->_M_guaranteed_capacity) > @@ -436,6 +501,7 @@ namespace __debug > > // element access: > _GLIBCXX_NODISCARD > + _GLIBCXX20_CONSTEXPR > reference > operator[](size_type __n) _GLIBCXX_NOEXCEPT > { > @@ -444,6 +510,7 @@ namespace __debug > } > > _GLIBCXX_NODISCARD > + _GLIBCXX20_CONSTEXPR > const_reference > operator[](size_type __n) const _GLIBCXX_NOEXCEPT > { > @@ -454,6 +521,7 @@ namespace __debug > using _Base::at; > > _GLIBCXX_NODISCARD > + _GLIBCXX20_CONSTEXPR > reference > front() _GLIBCXX_NOEXCEPT > { > @@ -462,6 +530,7 @@ namespace __debug > } > > _GLIBCXX_NODISCARD > + _GLIBCXX20_CONSTEXPR > const_reference > front() const _GLIBCXX_NOEXCEPT > { > @@ -470,6 +539,7 @@ namespace __debug > } > > _GLIBCXX_NODISCARD > + _GLIBCXX20_CONSTEXPR > reference > back() _GLIBCXX_NOEXCEPT > { > @@ -478,6 +548,7 @@ namespace __debug > } > > _GLIBCXX_NODISCARD > + _GLIBCXX20_CONSTEXPR > const_reference > back() const _GLIBCXX_NOEXCEPT > { > @@ -490,9 +561,13 @@ namespace __debug > using _Base::data; > > // 23.2.4.3 modifiers: > + _GLIBCXX20_CONSTEXPR > void > push_back(const _Tp& __x) > { > + if (std::__is_constant_evaluated()) > + return _Base::push_back(__x); > + > bool __realloc = this->_M_requires_reallocation(this->size() + 1); > _Base::push_back(__x); > if (__realloc) > @@ -502,12 +577,14 @@ namespace __debug > > #if __cplusplus >= 201103L > template<typename _Up = _Tp> > + _GLIBCXX20_CONSTEXPR > typename __gnu_cxx::__enable_if<!std::__are_same<_Up, bool>::__value, > void>::__type > push_back(_Tp&& __x) > { emplace_back(std::move(__x)); } > > template<typename... _Args> > + _GLIBCXX20_CONSTEXPR > #if __cplusplus > 201402L > reference > #else > @@ -515,6 +592,9 @@ namespace __debug > #endif > emplace_back(_Args&&... __args) > { > + if (std::__is_constant_evaluated()) > + return _Base::emplace_back(std::forward<_Args>(__args)...); > + > bool __realloc = this->_M_requires_reallocation(this->size() + 1); > _Base::emplace_back(std::forward<_Args>(__args)...); > if (__realloc) > @@ -526,19 +606,29 @@ namespace __debug > } > #endif > > + _GLIBCXX20_CONSTEXPR > void > pop_back() _GLIBCXX_NOEXCEPT > { > - __glibcxx_check_nonempty(); > - this->_M_invalidate_if(_Equal(--_Base::end())); > + if (!std::__is_constant_evaluated()) > + { > + __glibcxx_check_nonempty(); > + this->_M_invalidate_if(_Equal(--_Base::end())); > + } > _Base::pop_back(); > } > > #if __cplusplus >= 201103L > template<typename... _Args> > + _GLIBCXX20_CONSTEXPR > iterator > emplace(const_iterator __position, _Args&&... __args) > { > + if (std::__is_constant_evaluated()) > + return iterator(_Base::emplace(__position.base(), > + std::forward<_Args>(__args)...), > + this); > + > __glibcxx_check_insert(__position); > bool __realloc = this->_M_requires_reallocation(this->size() + 1); > difference_type __offset = __position.base() - _Base::cbegin(); > @@ -553,6 +643,7 @@ namespace __debug > } > #endif > > + _GLIBCXX20_CONSTEXPR > iterator > #if __cplusplus >= 201103L > insert(const_iterator __position, const _Tp& __x) > @@ -560,6 +651,9 @@ namespace __debug > insert(iterator __position, const _Tp& __x) > #endif > { > + if (std::__is_constant_evaluated()) > + return iterator(_Base::insert(__position.base(), __x), this); > + > __glibcxx_check_insert(__position); > bool __realloc = this->_M_requires_reallocation(this->size() + 1); > difference_type __offset = __position.base() - _Base::begin(); > @@ -574,20 +668,26 @@ namespace __debug > > #if __cplusplus >= 201103L > template<typename _Up = _Tp> > + _GLIBCXX20_CONSTEXPR > typename __gnu_cxx::__enable_if<!std::__are_same<_Up, bool>::__value, > iterator>::__type > insert(const_iterator __position, _Tp&& __x) > { return emplace(__position, std::move(__x)); } > > + _GLIBCXX20_CONSTEXPR > iterator > insert(const_iterator __position, initializer_list<value_type> __l) > { return this->insert(__position, __l.begin(), __l.end()); } > #endif > > #if __cplusplus >= 201103L > + _GLIBCXX20_CONSTEXPR > iterator > insert(const_iterator __position, size_type __n, const _Tp& __x) > { > + if (std::__is_constant_evaluated()) > + return iterator(_Base::insert(__position.base(), __n, __x), this); > + > __glibcxx_check_insert(__position); > bool __realloc = this->_M_requires_reallocation(this->size() + __n); > difference_type __offset = __position.base() - _Base::cbegin(); > @@ -618,10 +718,16 @@ namespace __debug > #if __cplusplus >= 201103L > template<class _InputIterator, > typename = std::_RequireInputIter<_InputIterator>> > + _GLIBCXX20_CONSTEXPR > iterator > insert(const_iterator __position, > _InputIterator __first, _InputIterator __last) > { > + if (std::__is_constant_evaluated()) > + return iterator(_Base::insert(__position.base(), > + __gnu_debug::__unsafe(__first), > + __gnu_debug::__unsafe(__last)), this); > + > typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist; > __glibcxx_check_insert_range(__position, __first, __last, __dist); > > @@ -673,6 +779,7 @@ namespace __debug > } > #endif > > + _GLIBCXX20_CONSTEXPR > iterator > #if __cplusplus >= 201103L > erase(const_iterator __position) > @@ -680,6 +787,9 @@ namespace __debug > erase(iterator __position) > #endif > { > + if (std::__is_constant_evaluated()) > + return iterator(_Base::erase(__position.base()), this); > + > __glibcxx_check_erase(__position); > difference_type __offset = __position.base() - _Base::begin(); > _Base_iterator __res = _Base::erase(__position.base()); > @@ -687,6 +797,7 @@ namespace __debug > return iterator(__res, this); > } > > + _GLIBCXX20_CONSTEXPR > iterator > #if __cplusplus >= 201103L > erase(const_iterator __first, const_iterator __last) > @@ -694,6 +805,9 @@ namespace __debug > erase(iterator __first, iterator __last) > #endif > { > + if (std::__is_constant_evaluated()) > + return iterator(_Base::erase(__first.base(), __last.base()), this); > + > // _GLIBCXX_RESOLVE_LIB_DEFECTS > // 151. can't currently clear() empty container > __glibcxx_check_erase_range(__first, __last); > @@ -714,25 +828,31 @@ namespace __debug > #endif > } > > + _GLIBCXX20_CONSTEXPR > void > swap(vector& __x) > _GLIBCXX_NOEXCEPT_IF( noexcept(declval<_Base&>().swap(__x)) ) > { > - _Safe::_M_swap(__x); > + if (!std::__is_constant_evaluated()) > + _Safe::_M_swap(__x); > _Base::swap(__x); > std::swap(this->_M_guaranteed_capacity, __x._M_guaranteed_capacity); > } > > + _GLIBCXX20_CONSTEXPR > void > clear() _GLIBCXX_NOEXCEPT > { > _Base::clear(); > - this->_M_invalidate_all(); > + if (!std::__is_constant_evaluated()) > + this->_M_invalidate_all(); > } > > + _GLIBCXX20_CONSTEXPR > _Base& > _M_base() _GLIBCXX_NOEXCEPT { return *this; } > > + _GLIBCXX20_CONSTEXPR > const _Base& > _M_base() const _GLIBCXX_NOEXCEPT { return *this; } > > @@ -746,6 +866,7 @@ namespace __debug > }; > > template<typename _Tp, typename _Alloc> > + _GLIBCXX20_CONSTEXPR > inline bool > operator==(const vector<_Tp, _Alloc>& __lhs, > const vector<_Tp, _Alloc>& __rhs) > @@ -789,6 +910,7 @@ namespace __debug > #endif // three-way comparison > > template<typename _Tp, typename _Alloc> > + _GLIBCXX20_CONSTEXPR > inline void > swap(vector<_Tp, _Alloc>& __lhs, vector<_Tp, _Alloc>& __rhs) > _GLIBCXX_NOEXCEPT_IF(noexcept(__lhs.swap(__rhs))) > diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/capacity/constexpr.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/capacity/constexpr.cc > index d44e9d97b46..534128c487e 100644 > --- a/libstdc++-v3/testsuite/23_containers/vector/bool/capacity/constexpr.cc > +++ b/libstdc++-v3/testsuite/23_containers/vector/bool/capacity/constexpr.cc > @@ -1,5 +1,4 @@ > // { dg-do compile { target c++20 } } > -// { dg-xfail-if "not supported" { debug_mode } } > > #include <vector> > #include <testsuite_hooks.h> > 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 66197e0aa29..e852c388903 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,7 +16,6 @@ > // <http://www.gnu.org/licenses/>. > > // { dg-do compile { target c++20 } } > -// { dg-xfail-if "not supported" { debug_mode } } > > #include <vector> > #include <testsuite_hooks.h> > diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/cons/constexpr.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/cons/constexpr.cc > index 0e0c1e1c5ec..88d99fe682f 100644 > --- a/libstdc++-v3/testsuite/23_containers/vector/bool/cons/constexpr.cc > +++ b/libstdc++-v3/testsuite/23_containers/vector/bool/cons/constexpr.cc > @@ -1,5 +1,4 @@ > // { dg-do compile { target c++20 } } > -// { dg-xfail-if "not supported" { debug_mode } } > > #include <vector> > #include <testsuite_hooks.h> > diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/element_access/1.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/element_access/1.cc > index 2a430845058..e7d710829e1 100644 > --- a/libstdc++-v3/testsuite/23_containers/vector/bool/element_access/1.cc > +++ b/libstdc++-v3/testsuite/23_containers/vector/bool/element_access/1.cc > @@ -1,5 +1,4 @@ > // { dg-do compile { target c++23 } } > -// { dg-xfail-if "not supported" { debug_mode } } > > #include <vector> > #include <testsuite_hooks.h> > 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 > index 5b8ca94e78f..d6b657e0161 100644 > --- a/libstdc++-v3/testsuite/23_containers/vector/bool/element_access/constexpr.cc > +++ b/libstdc++-v3/testsuite/23_containers/vector/bool/element_access/constexpr.cc > @@ -1,5 +1,4 @@ > // { dg-do compile { target c++20 } } > -// { dg-xfail-if "not supported" { debug_mode } } > > #include <vector> > #include <testsuite_hooks.h> > 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 > index 3ad7dda88a9..31a6793f7ff 100644 > --- a/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/assign/constexpr.cc > +++ b/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/assign/constexpr.cc > @@ -1,5 +1,4 @@ > // { dg-do compile { target c++20 } } > -// { dg-xfail-if "not supported" { debug_mode } } > > #include <vector> > #include <testsuite_hooks.h> > diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/constexpr.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/constexpr.cc > index 22a4df5e370..0e37f9aa786 100644 > --- a/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/constexpr.cc > +++ b/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/constexpr.cc > @@ -1,5 +1,4 @@ > // { dg-do compile { target c++20 } } > -// { dg-xfail-if "not supported" { debug_mode } } > > #include <vector> > #include <testsuite_hooks.h> > 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 > index 624ff96a9e9..d2a0218a109 100644 > --- a/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/swap/constexpr.cc > +++ b/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/swap/constexpr.cc > @@ -1,5 +1,4 @@ > // { dg-do compile { target c++20 } } > -// { dg-xfail-if "not supported" { debug_mode } } > > #include <vector> > #include <utility> > @@ -49,6 +48,7 @@ test_member_swap() > > static_assert(test_member_swap()); > > +#ifndef _GLIBCXX_DEBUG > constexpr bool > test_reference_swap() > { > @@ -63,3 +63,4 @@ test_reference_swap() > } > > static_assert(test_reference_swap()); > +#endif > diff --git a/libstdc++-v3/testsuite/23_containers/vector/capacity/constexpr.cc b/libstdc++-v3/testsuite/23_containers/vector/capacity/constexpr.cc > index 018a4792891..c331dbd5e57 100644 > --- a/libstdc++-v3/testsuite/23_containers/vector/capacity/constexpr.cc > +++ b/libstdc++-v3/testsuite/23_containers/vector/capacity/constexpr.cc > @@ -1,5 +1,4 @@ > // { dg-do compile { target c++20 } } > -// { dg-xfail-if "not supported" { debug_mode } } > > #include <vector> > #include <testsuite_hooks.h> > 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 72c5c6cd7f9..63cb92c0edf 100644 > --- a/libstdc++-v3/testsuite/23_containers/vector/cmp_c++20.cc > +++ b/libstdc++-v3/testsuite/23_containers/vector/cmp_c++20.cc > @@ -16,7 +16,6 @@ > // <http://www.gnu.org/licenses/>. > > // { dg-do compile { target c++20 } } > -// { dg-xfail-if "not supported" { debug_mode } } > > #include <vector> > #include <testsuite_hooks.h> > diff --git a/libstdc++-v3/testsuite/23_containers/vector/cons/constexpr.cc b/libstdc++-v3/testsuite/23_containers/vector/cons/constexpr.cc > index 7bf86511240..fa78676b300 100644 > --- a/libstdc++-v3/testsuite/23_containers/vector/cons/constexpr.cc > +++ b/libstdc++-v3/testsuite/23_containers/vector/cons/constexpr.cc > @@ -1,6 +1,5 @@ > // { dg-do compile { target c++20 } } > // { dg-add-options no_pch } > -// { dg-xfail-if "not supported" { debug_mode } } > > #include <vector> > > diff --git a/libstdc++-v3/testsuite/23_containers/vector/data_access/constexpr.cc b/libstdc++-v3/testsuite/23_containers/vector/data_access/constexpr.cc > index f5b601a44f4..142050e8f03 100644 > --- a/libstdc++-v3/testsuite/23_containers/vector/data_access/constexpr.cc > +++ b/libstdc++-v3/testsuite/23_containers/vector/data_access/constexpr.cc > @@ -1,5 +1,4 @@ > // { dg-do compile { target c++20 } } > -// { dg-xfail-if "not supported" { debug_mode } } > > #include <vector> > #include <testsuite_hooks.h> > diff --git a/libstdc++-v3/testsuite/23_containers/vector/element_access/constexpr.cc b/libstdc++-v3/testsuite/23_containers/vector/element_access/constexpr.cc > index 60c66dcc647..ee93d2fd95e 100644 > --- a/libstdc++-v3/testsuite/23_containers/vector/element_access/constexpr.cc > +++ b/libstdc++-v3/testsuite/23_containers/vector/element_access/constexpr.cc > @@ -1,5 +1,4 @@ > // { dg-do compile { target c++20 } } > -// { dg-xfail-if "not supported" { debug_mode } } > > #include <vector> > #include <testsuite_hooks.h> > diff --git a/libstdc++-v3/testsuite/23_containers/vector/modifiers/assign/constexpr.cc b/libstdc++-v3/testsuite/23_containers/vector/modifiers/assign/constexpr.cc > index cca20f4291c..41fc8d9696e 100644 > --- a/libstdc++-v3/testsuite/23_containers/vector/modifiers/assign/constexpr.cc > +++ b/libstdc++-v3/testsuite/23_containers/vector/modifiers/assign/constexpr.cc > @@ -1,5 +1,4 @@ > // { dg-do compile { target c++20 } } > -// { dg-xfail-if "not supported" { debug_mode } } > > #include <vector> > #include <testsuite_hooks.h> > diff --git a/libstdc++-v3/testsuite/23_containers/vector/modifiers/constexpr.cc b/libstdc++-v3/testsuite/23_containers/vector/modifiers/constexpr.cc > index 766e3a7690f..4aa1f1f67b7 100644 > --- a/libstdc++-v3/testsuite/23_containers/vector/modifiers/constexpr.cc > +++ b/libstdc++-v3/testsuite/23_containers/vector/modifiers/constexpr.cc > @@ -1,5 +1,4 @@ > // { dg-do compile { target c++20 } } > -// { dg-xfail-if "not supported" { debug_mode } } > > #include <vector> > #include <testsuite_hooks.h> > diff --git a/libstdc++-v3/testsuite/23_containers/vector/modifiers/swap/constexpr.cc b/libstdc++-v3/testsuite/23_containers/vector/modifiers/swap/constexpr.cc > index 45b3986beca..77d2a518d69 100644 > --- a/libstdc++-v3/testsuite/23_containers/vector/modifiers/swap/constexpr.cc > +++ b/libstdc++-v3/testsuite/23_containers/vector/modifiers/swap/constexpr.cc > @@ -1,5 +1,4 @@ > // { dg-do compile { target c++20 } } > -// { dg-xfail-if "not supported" { debug_mode } } > > #include <vector> > #include <utility> > -- > 2.43.0 > >
On Sat, 16 Dec 2023 at 00:27, Patrick Palka wrote: > > On Wed, 6 Dec 2023, Jonathan Wakely wrote: > > > Any comments on this approach? > > > > -- >8 -- > > > > This makes constexpr std::vector (mostly) work in Debug Mode. All safe > > iterator instrumentation and checking is disabled during constant > > evaluation, because it requires mutex locks and calls to non-inline > > functions defined in libstdc++.so. It should be OK to disable the safety > > checks, because most UB should be detected during constant evaluation > > anyway. > > > > We could try to enable the full checking in constexpr, but it would mean > > wrapping all the non-inline functions like _M_attach with an inline > > _M_constexpr_attach that does the iterator housekeeping inline without > > mutex locks when calling for constant evaluation, and calls the > > non-inline function at runtime. That could be done in future if we find > > that we've lost safety or useful checking by disabling the safe > > iterators. > > > > There are a few test failures in C++20 mode, which I'm unable to > > explain. The _Safe_iterator::operator++() member gives errors for using > > non-constexpr functions during constant evaluation, even though those > > functions are guarded by std::is_constant_evaluated() checks. The same > > code works fine for C++23 and up. > > AFAICT these C++20 test failures are really due to the variable > definition of non-literal type > > 381 __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); > > which were prohibited in a constexpr function (even if that code was > never executed) until C++23's P2242R3. Ah, I figured it was a core change but I couldn't recall which one. Thanks. > We can use an immediately invoked lambda to work around this: > > 381 [this] { > 382 __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); > 383 ++base(); > 384 }(); > 385 return *this; We'd need some #if as this code has to work for C++98. But that's doable. > > > > libstdc++-v3/ChangeLog: > > > > PR libstdc++/109536 > > * include/bits/c++config (__glibcxx_constexpr_assert): Remove > > macro. > > * include/bits/stl_algobase.h (__niter_base, __copy_move_a) > > (__copy_move_backward_a, __fill_a, __fill_n_a, __equal_aux) > > (__lexicographical_compare_aux): Add constexpr to overloads for > > debug mode iterators. > > * include/debug/helper_functions.h (__unsafe): Add constexpr. > > * include/debug/macros.h (_GLIBCXX_DEBUG_VERIFY_COND_AT): Remove > > macro, folding it into ... > > (_GLIBCXX_DEBUG_VERIFY_AT_F): ... here. Do not use > > __glibcxx_constexpr_assert. > > * include/debug/safe_base.h (_Safe_iterator_base): Add constexpr > > to some member functions. Omit attaching, detaching and checking > > operations during constant evaluation. > > * include/debug/safe_container.h (_Safe_container): Likewise. > > * include/debug/safe_iterator.h (_Safe_iterator): Likewise. > > * include/debug/safe_iterator.tcc (__niter_base, __copy_move_a) > > (__copy_move_backward_a, __fill_a, __fill_n_a, __equal_aux) > > (__lexicographical_compare_aux): Add constexpr. > > * include/debug/vector (_Safe_vector, vector): Add constexpr. > > Omit safe iterator operations during constant evaluation. > > * testsuite/23_containers/vector/bool/capacity/constexpr.cc: > > Remove dg-xfail-if for debug mode. > > * testsuite/23_containers/vector/bool/cmp_c++20.cc: Likewise. > > * testsuite/23_containers/vector/bool/cons/constexpr.cc: > > Likewise. > > * testsuite/23_containers/vector/bool/element_access/1.cc: > > Likewise. > > * testsuite/23_containers/vector/bool/element_access/constexpr.cc: > > Likewise. > > * testsuite/23_containers/vector/bool/modifiers/assign/constexpr.cc: > > Likewise. > > * testsuite/23_containers/vector/bool/modifiers/constexpr.cc: > > Likewise. > > * testsuite/23_containers/vector/bool/modifiers/swap/constexpr.cc: > > Likewise. > > * testsuite/23_containers/vector/capacity/constexpr.cc: > > Likewise. > > * testsuite/23_containers/vector/cmp_c++20.cc: Likewise. > > * testsuite/23_containers/vector/cons/constexpr.cc: Likewise. > > * testsuite/23_containers/vector/data_access/constexpr.cc: > > Likewise. > > * testsuite/23_containers/vector/element_access/constexpr.cc: > > Likewise. > > * testsuite/23_containers/vector/modifiers/assign/constexpr.cc: > > Likewise. > > * testsuite/23_containers/vector/modifiers/constexpr.cc: > > Likewise. > > * testsuite/23_containers/vector/modifiers/swap/constexpr.cc: > > Likewise. > > --- > > libstdc++-v3/include/bits/c++config | 9 - > > libstdc++-v3/include/bits/stl_algobase.h | 15 ++ > > libstdc++-v3/include/debug/helper_functions.h | 1 + > > libstdc++-v3/include/debug/macros.h | 9 +- > > libstdc++-v3/include/debug/safe_base.h | 35 +++- > > libstdc++-v3/include/debug/safe_container.h | 15 +- > > libstdc++-v3/include/debug/safe_iterator.h | 186 +++++++++++++++--- > > libstdc++-v3/include/debug/safe_iterator.tcc | 15 ++ > > libstdc++-v3/include/debug/vector | 146 ++++++++++++-- > > .../vector/bool/capacity/constexpr.cc | 1 - > > .../23_containers/vector/bool/cmp_c++20.cc | 1 - > > .../vector/bool/cons/constexpr.cc | 1 - > > .../vector/bool/element_access/1.cc | 1 - > > .../vector/bool/element_access/constexpr.cc | 1 - > > .../vector/bool/modifiers/assign/constexpr.cc | 1 - > > .../vector/bool/modifiers/constexpr.cc | 1 - > > .../vector/bool/modifiers/swap/constexpr.cc | 3 +- > > .../vector/capacity/constexpr.cc | 1 - > > .../23_containers/vector/cmp_c++20.cc | 1 - > > .../23_containers/vector/cons/constexpr.cc | 1 - > > .../vector/data_access/constexpr.cc | 1 - > > .../vector/element_access/constexpr.cc | 1 - > > .../vector/modifiers/assign/constexpr.cc | 1 - > > .../vector/modifiers/constexpr.cc | 1 - > > .../vector/modifiers/swap/constexpr.cc | 1 - > > 25 files changed, 369 insertions(+), 80 deletions(-) > > > > diff --git a/libstdc++-v3/include/bits/c++config b/libstdc++-v3/include/bits/c++config > > index 284d24d933f..13d416845c3 100644 > > --- a/libstdc++-v3/include/bits/c++config > > +++ b/libstdc++-v3/include/bits/c++config > > @@ -565,15 +565,6 @@ namespace std > > # define _GLIBCXX_EXTERN_TEMPLATE -1 > > #endif > > > > - > > -#if _GLIBCXX_HAVE_IS_CONSTANT_EVALUATED > > -# define __glibcxx_constexpr_assert(cond) \ > > - if (std::__is_constant_evaluated() && !bool(cond)) \ > > - __builtin_unreachable() /* precondition violation detected! */ > > -#else > > -# define __glibcxx_constexpr_assert(unevaluated) > > -#endif > > - > > #undef _GLIBCXX_VERBOSE_ASSERT > > > > // Assert. > > diff --git a/libstdc++-v3/include/bits/stl_algobase.h b/libstdc++-v3/include/bits/stl_algobase.h > > index 01ca4496dfd..77d0ee7bcf5 100644 > > --- a/libstdc++-v3/include/bits/stl_algobase.h > > +++ b/libstdc++-v3/include/bits/stl_algobase.h > > @@ -318,6 +318,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > { return __it; } > > > > template<typename _Ite, typename _Seq> > > + _GLIBCXX20_CONSTEXPR > > _Ite > > __niter_base(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, > > std::random_access_iterator_tag>&); > > @@ -545,6 +546,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER > > > > template<bool _IsMove, > > typename _Ite, typename _Seq, typename _Cat, typename _OI> > > + _GLIBCXX20_CONSTEXPR > > _OI > > __copy_move_a(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>&, > > const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>&, > > @@ -552,6 +554,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER > > > > template<bool _IsMove, > > typename _II, typename _Ite, typename _Seq, typename _Cat> > > + _GLIBCXX20_CONSTEXPR > > __gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat> > > __copy_move_a(_II, _II, > > const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>&); > > @@ -559,6 +562,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER > > template<bool _IsMove, > > typename _IIte, typename _ISeq, typename _ICat, > > typename _OIte, typename _OSeq, typename _OCat> > > + _GLIBCXX20_CONSTEXPR > > ::__gnu_debug::_Safe_iterator<_OIte, _OSeq, _OCat> > > __copy_move_a(const ::__gnu_debug::_Safe_iterator<_IIte, _ISeq, _ICat>&, > > const ::__gnu_debug::_Safe_iterator<_IIte, _ISeq, _ICat>&, > > @@ -812,6 +816,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER > > > > template<bool _IsMove, > > typename _Ite, typename _Seq, typename _Cat, typename _OI> > > + _GLIBCXX20_CONSTEXPR > > _OI > > __copy_move_backward_a( > > const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>&, > > @@ -820,6 +825,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER > > > > template<bool _IsMove, > > typename _II, typename _Ite, typename _Seq, typename _Cat> > > + _GLIBCXX20_CONSTEXPR > > __gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat> > > __copy_move_backward_a(_II, _II, > > const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>&); > > @@ -827,6 +833,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER > > template<bool _IsMove, > > typename _IIte, typename _ISeq, typename _ICat, > > typename _OIte, typename _OSeq, typename _OCat> > > + _GLIBCXX20_CONSTEXPR > > ::__gnu_debug::_Safe_iterator<_OIte, _OSeq, _OCat> > > __copy_move_backward_a( > > const ::__gnu_debug::_Safe_iterator<_IIte, _ISeq, _ICat>&, > > @@ -977,6 +984,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER > > { std::__fill_a1(__first, __last, __value); } > > > > template<typename _Ite, typename _Seq, typename _Cat, typename _Tp> > > + _GLIBCXX20_CONSTEXPR > > void > > __fill_a(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>&, > > const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>&, > > @@ -1082,6 +1090,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER > > > > template<typename _Ite, typename _Seq, typename _Cat, typename _Size, > > typename _Tp> > > + _GLIBCXX20_CONSTEXPR > > ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat> > > __fill_n_a(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>& __first, > > _Size __n, const _Tp& __value, > > @@ -1230,18 +1239,21 @@ _GLIBCXX_END_NAMESPACE_CONTAINER > > } > > > > template<typename _II1, typename _Seq1, typename _Cat1, typename _II2> > > + _GLIBCXX20_CONSTEXPR > > bool > > __equal_aux(const ::__gnu_debug::_Safe_iterator<_II1, _Seq1, _Cat1>&, > > const ::__gnu_debug::_Safe_iterator<_II1, _Seq1, _Cat1>&, > > _II2); > > > > template<typename _II1, typename _II2, typename _Seq2, typename _Cat2> > > + _GLIBCXX20_CONSTEXPR > > bool > > __equal_aux(_II1, _II1, > > const ::__gnu_debug::_Safe_iterator<_II2, _Seq2, _Cat2>&); > > > > template<typename _II1, typename _Seq1, typename _Cat1, > > typename _II2, typename _Seq2, typename _Cat2> > > + _GLIBCXX20_CONSTEXPR > > bool > > __equal_aux(const ::__gnu_debug::_Safe_iterator<_II1, _Seq1, _Cat1>&, > > const ::__gnu_debug::_Safe_iterator<_II1, _Seq1, _Cat1>&, > > @@ -1430,6 +1442,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER > > > > template<typename _Iter1, typename _Seq1, typename _Cat1, > > typename _II2> > > + _GLIBCXX20_CONSTEXPR > > bool > > __lexicographical_compare_aux( > > const ::__gnu_debug::_Safe_iterator<_Iter1, _Seq1, _Cat1>&, > > @@ -1438,6 +1451,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER > > > > template<typename _II1, > > typename _Iter2, typename _Seq2, typename _Cat2> > > + _GLIBCXX20_CONSTEXPR > > bool > > __lexicographical_compare_aux( > > _II1, _II1, > > @@ -1446,6 +1460,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER > > > > template<typename _Iter1, typename _Seq1, typename _Cat1, > > typename _Iter2, typename _Seq2, typename _Cat2> > > + _GLIBCXX20_CONSTEXPR > > bool > > __lexicographical_compare_aux( > > const ::__gnu_debug::_Safe_iterator<_Iter1, _Seq1, _Cat1>&, > > diff --git a/libstdc++-v3/include/debug/helper_functions.h b/libstdc++-v3/include/debug/helper_functions.h > > index 052b36b484c..4b76cb00f9a 100644 > > --- a/libstdc++-v3/include/debug/helper_functions.h > > +++ b/libstdc++-v3/include/debug/helper_functions.h > > @@ -324,6 +324,7 @@ namespace __gnu_debug > > > > /* Remove debug mode safe iterator layer, if any. */ > > template<typename _Iterator> > > + _GLIBCXX_CONSTEXPR > > inline _Iterator > > __unsafe(_Iterator __it) > > { return __it; } > > diff --git a/libstdc++-v3/include/debug/macros.h b/libstdc++-v3/include/debug/macros.h > > index 0fef0a006fc..4a3d0f2ea84 100644 > > --- a/libstdc++-v3/include/debug/macros.h > > +++ b/libstdc++-v3/include/debug/macros.h > > @@ -38,15 +38,12 @@ > > * the user error and where the error is reported. > > * > > */ > > -#define _GLIBCXX_DEBUG_VERIFY_COND_AT(_Cond,_ErrMsg,_File,_Line,_Func) \ > > - if (__builtin_expect(!bool(_Cond), false)) \ > > - __gnu_debug::_Error_formatter::_S_at(_File, _Line, _Func) \ > > - ._ErrMsg._M_error() > > > > #define _GLIBCXX_DEBUG_VERIFY_AT_F(_Cond,_ErrMsg,_File,_Line,_Func) \ > > do { \ > > - __glibcxx_constexpr_assert(_Cond); \ > > - _GLIBCXX_DEBUG_VERIFY_COND_AT(_Cond,_ErrMsg,_File,_Line,_Func); \ > > + if (__builtin_expect(!bool(_Cond), false)) \ > > + __gnu_debug::_Error_formatter::_S_at(_File, _Line, _Func) \ > > + ._ErrMsg._M_error(); \ > > } while (false) > > > > #define _GLIBCXX_DEBUG_VERIFY_AT(_Cond,_ErrMsg,_File,_Line) \ > > diff --git a/libstdc++-v3/include/debug/safe_base.h b/libstdc++-v3/include/debug/safe_base.h > > index 1dfa9f68b65..d9c17b52b48 100644 > > --- a/libstdc++-v3/include/debug/safe_base.h > > +++ b/libstdc++-v3/include/debug/safe_base.h > > @@ -75,6 +75,7 @@ namespace __gnu_debug > > > > protected: > > /** Initializes the iterator and makes it singular. */ > > + _GLIBCXX20_CONSTEXPR > > _Safe_iterator_base() > > : _M_sequence(0), _M_version(0), _M_prior(0), _M_next(0) > > { } > > @@ -86,18 +87,31 @@ namespace __gnu_debug > > * singular. Otherwise, the iterator will reference @p __seq and > > * be nonsingular. > > */ > > + _GLIBCXX20_CONSTEXPR > > _Safe_iterator_base(const _Safe_sequence_base* __seq, bool __constant) > > : _M_sequence(0), _M_version(0), _M_prior(0), _M_next(0) > > - { this->_M_attach(const_cast<_Safe_sequence_base*>(__seq), __constant); } > > + { > > + if (!std::__is_constant_evaluated()) > > + this->_M_attach(const_cast<_Safe_sequence_base*>(__seq), __constant); > > + } > > > > /** Initializes the iterator to reference the same sequence that > > @p __x does. @p __constant is true if this is a constant > > iterator, and false if it is mutable. */ > > + _GLIBCXX20_CONSTEXPR > > _Safe_iterator_base(const _Safe_iterator_base& __x, bool __constant) > > : _M_sequence(0), _M_version(0), _M_prior(0), _M_next(0) > > - { this->_M_attach(__x._M_sequence, __constant); } > > + { > > + if (!std::__is_constant_evaluated()) > > + this->_M_attach(__x._M_sequence, __constant); > > + } > > > > - ~_Safe_iterator_base() { this->_M_detach(); } > > + _GLIBCXX20_CONSTEXPR > > + ~_Safe_iterator_base() > > + { > > + if (!std::__is_constant_evaluated()) > > + this->_M_detach(); > > + } > > > > /** For use in _Safe_iterator. */ > > __gnu_cxx::__mutex& > > @@ -201,24 +215,34 @@ namespace __gnu_debug > > > > protected: > > // Initialize with a version number of 1 and no iterators > > + _GLIBCXX20_CONSTEXPR > > _Safe_sequence_base() _GLIBCXX_NOEXCEPT > > : _M_iterators(0), _M_const_iterators(0), _M_version(1) > > { } > > > > #if __cplusplus >= 201103L > > + _GLIBCXX20_CONSTEXPR > > _Safe_sequence_base(const _Safe_sequence_base&) noexcept > > : _Safe_sequence_base() { } > > > > // Move constructor swap iterators. > > + _GLIBCXX20_CONSTEXPR > > _Safe_sequence_base(_Safe_sequence_base&& __seq) noexcept > > : _Safe_sequence_base() > > - { _M_swap(__seq); } > > + { > > + if (!std::__is_constant_evaluated()) > > + _M_swap(__seq); > > + } > > #endif > > > > /** Notify all iterators that reference this sequence that the > > sequence is being destroyed. */ > > + _GLIBCXX20_CONSTEXPR > > ~_Safe_sequence_base() > > - { this->_M_detach_all(); } > > + { > > + if (!std::__is_constant_evaluated()) > > + this->_M_detach_all(); > > + } > > > > /** Detach all iterators, leaving them singular. */ > > void > > @@ -244,6 +268,7 @@ namespace __gnu_debug > > * operation is complete all iterators that originally referenced > > * one container now reference the other container. > > */ > > + _GLIBCXX20_CONSTEXPR > > void > > _M_swap(_Safe_sequence_base& __x) _GLIBCXX_USE_NOEXCEPT; > > With -Wsystem-headers on some ranges tests I get: > > /gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/debug/safe_base.h:273:5: warning: inline function ‘constexpr void __gnu_debug::_Safe_sequence_base::_M_swap(__gnu_debug::_Safe_sequence_base&)’ used but never defined > 273 | _M_swap(_Safe_sequence_base& __x) _GLIBCXX_USE_NOEXCEPT; > | ^~~~~~~ Oh I think we can remove the CONSTEXPR macro. I added it too aggressively and forgot to remove it again in some places.
On Sat, 16 Dec 2023 at 09:14, Jonathan Wakely wrote: > > On Sat, 16 Dec 2023 at 00:27, Patrick Palka wrote: > > > > On Wed, 6 Dec 2023, Jonathan Wakely wrote: > > > > > Any comments on this approach? > > > > > > -- >8 -- > > > > > > This makes constexpr std::vector (mostly) work in Debug Mode. All safe > > > iterator instrumentation and checking is disabled during constant > > > evaluation, because it requires mutex locks and calls to non-inline > > > functions defined in libstdc++.so. It should be OK to disable the safety > > > checks, because most UB should be detected during constant evaluation > > > anyway. > > > > > > We could try to enable the full checking in constexpr, but it would mean > > > wrapping all the non-inline functions like _M_attach with an inline > > > _M_constexpr_attach that does the iterator housekeeping inline without > > > mutex locks when calling for constant evaluation, and calls the > > > non-inline function at runtime. That could be done in future if we find > > > that we've lost safety or useful checking by disabling the safe > > > iterators. > > > > > > There are a few test failures in C++20 mode, which I'm unable to > > > explain. The _Safe_iterator::operator++() member gives errors for using > > > non-constexpr functions during constant evaluation, even though those > > > functions are guarded by std::is_constant_evaluated() checks. The same > > > code works fine for C++23 and up. > > > > AFAICT these C++20 test failures are really due to the variable > > definition of non-literal type > > > > 381 __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); > > > > which were prohibited in a constexpr function (even if that code was > > never executed) until C++23's P2242R3. > > Ah, I figured it was a core change but I couldn't recall which one. Thanks. > > > We can use an immediately invoked lambda to work around this: > > > > 381 [this] { > > 382 __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); > > 383 ++base(); > > 384 }(); > > 385 return *this; > > We'd need some #if as this code has to work for C++98. But that's doable. The attached patch seems simpler, I'm testing it now. commit 5d70c6c2965647077749a869e9cdbf7e91dba4c7 Author: Jonathan Wakely <jwakely@redhat.com> Date: Sat Dec 16 09:31:40 2023 libstdc++: Fix errors for constexpr __gnu_debug::vector in C++23 [PR109536] In the commit log for r14-6553-g7d00a59229ee17 I noted some tests FAIL in C++20 mode. Patrick identified that they were due to the variable definitions of non-literal type __scoped_lock, which were prohibited in a constexpr function (even if that code was never executed) until C++23's P2242R3. We can move the problematic code into new non-constexpr functions that are not called during constant evaluation. There's also a warning about a constexpr _M_swap function which is never defined. That's simply because I added the _GLIBCXX20_CONSTEXPR macro on a member that doesn't need it. libstdc++-v3/ChangeLog: PR libstdc++/109536 * include/debug/safe_base.h (_Safe_sequence_base::_M_swap): Remove _GLIBCXX20_CONSTEXPR from non-inline member function. * include/debug/safe_iterator.h (_Safe_iterator::_M_move_assign) diff --git a/libstdc++-v3/include/debug/safe_base.h b/libstdc++-v3/include/debug/safe_base.h index d9c17b52b48..1519ad809a4 100644 --- a/libstdc++-v3/include/debug/safe_base.h +++ b/libstdc++-v3/include/debug/safe_base.h @@ -268,7 +268,6 @@ namespace __gnu_debug * operation is complete all iterators that originally referenced * one container now reference the other container. */ - _GLIBCXX20_CONSTEXPR void _M_swap(_Safe_sequence_base& __x) _GLIBCXX_USE_NOEXCEPT; diff --git a/libstdc++-v3/include/debug/safe_iterator.h b/libstdc++-v3/include/debug/safe_iterator.h index 26f008982f8..bde34e1f99c 100644 --- a/libstdc++-v3/include/debug/safe_iterator.h +++ b/libstdc++-v3/include/debug/safe_iterator.h @@ -295,7 +295,13 @@ namespace __gnu_debug base() = __x.base(); return *this; } + _M_move_assign(std::move(__x)); + return *this; + } + void + _M_move_assign(_Safe_iterator&& __x) noexcept + { _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() || __x._M_value_initialized(), _M_message(__msg_copy_singular) @@ -303,7 +309,7 @@ namespace __gnu_debug ._M_iterator(__x, "other")); if (std::__addressof(__x) == this) - return *this; + return; if (this->_M_sequence && this->_M_sequence == __x._M_sequence) { @@ -320,7 +326,6 @@ namespace __gnu_debug __x._M_detach(); __x.base() = _Iterator(); - return *this; } #endif @@ -370,17 +375,20 @@ namespace __gnu_debug operator++() _GLIBCXX_NOEXCEPT { if (std::__is_constant_evaluated()) - { - ++base(); - return *this; - } + ++base(); + else + _M_increment(); + return *this; + } + void + _M_increment() _GLIBCXX_NOEXCEPT + { _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(), _M_message(__msg_bad_inc) ._M_iterator(*this, "this")); __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); ++base(); - return *this; } /** @@ -689,17 +697,20 @@ namespace __gnu_debug operator--() _GLIBCXX_NOEXCEPT { if (std::__is_constant_evaluated()) - { - --this->base(); - return *this; - } + --this->base(); + else + _M_decrement(); + return *this; + } + void + _M_decrement() _GLIBCXX_NOEXCEPT + { _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(), _M_message(__msg_bad_dec) ._M_iterator(*this, "this")); __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); --this->base(); - return *this; } /**
On Sat, 16 Dec 2023, Jonathan Wakely wrote: > On Sat, 16 Dec 2023 at 09:14, Jonathan Wakely wrote: > > > > On Sat, 16 Dec 2023 at 00:27, Patrick Palka wrote: > > > > > > On Wed, 6 Dec 2023, Jonathan Wakely wrote: > > > > > > > Any comments on this approach? > > > > > > > > -- >8 -- > > > > > > > > This makes constexpr std::vector (mostly) work in Debug Mode. All safe > > > > iterator instrumentation and checking is disabled during constant > > > > evaluation, because it requires mutex locks and calls to non-inline > > > > functions defined in libstdc++.so. It should be OK to disable the safety > > > > checks, because most UB should be detected during constant evaluation > > > > anyway. > > > > > > > > We could try to enable the full checking in constexpr, but it would mean > > > > wrapping all the non-inline functions like _M_attach with an inline > > > > _M_constexpr_attach that does the iterator housekeeping inline without > > > > mutex locks when calling for constant evaluation, and calls the > > > > non-inline function at runtime. That could be done in future if we find > > > > that we've lost safety or useful checking by disabling the safe > > > > iterators. > > > > > > > > There are a few test failures in C++20 mode, which I'm unable to > > > > explain. The _Safe_iterator::operator++() member gives errors for using > > > > non-constexpr functions during constant evaluation, even though those > > > > functions are guarded by std::is_constant_evaluated() checks. The same > > > > code works fine for C++23 and up. > > > > > > AFAICT these C++20 test failures are really due to the variable > > > definition of non-literal type > > > > > > 381 __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); > > > > > > which were prohibited in a constexpr function (even if that code was > > > never executed) until C++23's P2242R3. > > > > Ah, I figured it was a core change but I couldn't recall which one. Thanks. Yeah the diagnostic blaming the non-constexpr call to _M_incrementable was outright wrong and misleading, I filed PR113041 about that. > > > > > We can use an immediately invoked lambda to work around this: > > > > > > 381 [this] { > > > 382 __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); > > > 383 ++base(); > > > 384 }(); > > > 385 return *this; > > > > We'd need some #if as this code has to work for C++98. But that's doable. > > The attached patch seems simpler, I'm testing it now. Would the operator+=, operator-= and the copy assign operator= also need adjustment? We could somewhat cleanly encapsulate the lambda workaround with a pair of macros surrounding the problematic variable, something like: diff --git a/libstdc++-v3/include/debug/safe_iterator.h b/libstdc++-v3/include/debug/safe_iterator.h index 26f008982f8..df3b4d33f04 100644 --- a/libstdc++-v3/include/debug/safe_iterator.h +++ b/libstdc++-v3/include/debug/safe_iterator.h @@ -360,6 +360,14 @@ namespace __gnu_debug return base().operator->(); } +#if __cplusplus >= 202002L && __cpp_constexpr < 202110L +# define _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_BEGIN [&] { do +# define _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_END while(false); }() +#else +# define _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_BEGIN do +# define _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_END while(false) +#endif + // ------ Input iterator requirements ------ /** * @brief Iterator preincrement @@ -378,8 +386,10 @@ namespace __gnu_debug _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(), _M_message(__msg_bad_inc) ._M_iterator(*this, "this")); - __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); - ++base(); + _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_BEGIN { + __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); + ++base(); + } _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_END; return *this; }
On Sat, 16 Dec 2023 at 16:26, Patrick Palka <ppalka@redhat.com> wrote: > > On Sat, 16 Dec 2023, Jonathan Wakely wrote: > > > On Sat, 16 Dec 2023 at 09:14, Jonathan Wakely wrote: > > > > > > On Sat, 16 Dec 2023 at 00:27, Patrick Palka wrote: > > > > > > > > On Wed, 6 Dec 2023, Jonathan Wakely wrote: > > > > > > > > > Any comments on this approach? > > > > > > > > > > -- >8 -- > > > > > > > > > > This makes constexpr std::vector (mostly) work in Debug Mode. All safe > > > > > iterator instrumentation and checking is disabled during constant > > > > > evaluation, because it requires mutex locks and calls to non-inline > > > > > functions defined in libstdc++.so. It should be OK to disable the safety > > > > > checks, because most UB should be detected during constant evaluation > > > > > anyway. > > > > > > > > > > We could try to enable the full checking in constexpr, but it would mean > > > > > wrapping all the non-inline functions like _M_attach with an inline > > > > > _M_constexpr_attach that does the iterator housekeeping inline without > > > > > mutex locks when calling for constant evaluation, and calls the > > > > > non-inline function at runtime. That could be done in future if we find > > > > > that we've lost safety or useful checking by disabling the safe > > > > > iterators. > > > > > > > > > > There are a few test failures in C++20 mode, which I'm unable to > > > > > explain. The _Safe_iterator::operator++() member gives errors for using > > > > > non-constexpr functions during constant evaluation, even though those > > > > > functions are guarded by std::is_constant_evaluated() checks. The same > > > > > code works fine for C++23 and up. > > > > > > > > AFAICT these C++20 test failures are really due to the variable > > > > definition of non-literal type > > > > > > > > 381 __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); > > > > > > > > which were prohibited in a constexpr function (even if that code was > > > > never executed) until C++23's P2242R3. > > > > > > Ah, I figured it was a core change but I couldn't recall which one. Thanks. > > Yeah the diagnostic blaming the non-constexpr call to _M_incrementable > was outright wrong and misleading, I filed PR113041 about that. > > > > > > > > We can use an immediately invoked lambda to work around this: > > > > > > > > 381 [this] { > > > > 382 __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); > > > > 383 ++base(); > > > > 384 }(); > > > > 385 return *this; > > > > > > We'd need some #if as this code has to work for C++98. But that's doable. > > > > The attached patch seems simpler, I'm testing it now. > > Would the operator+=, operator-= and the copy assign operator= also need > adjustment? Maybe ... which suggest we have missing tests for constexpr vector (which is probably the case). > > We could somewhat cleanly encapsulate the lambda workaround with a pair > of macros surrounding the problematic variable, something like: > > diff --git a/libstdc++-v3/include/debug/safe_iterator.h b/libstdc++-v3/include/debug/safe_iterator.h > index 26f008982f8..df3b4d33f04 100644 > --- a/libstdc++-v3/include/debug/safe_iterator.h > +++ b/libstdc++-v3/include/debug/safe_iterator.h > @@ -360,6 +360,14 @@ namespace __gnu_debug > return base().operator->(); > } > > +#if __cplusplus >= 202002L && __cpp_constexpr < 202110L > +# define _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_BEGIN [&] { do > +# define _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_END while(false); }() > +#else > +# define _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_BEGIN do > +# define _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_END while(false) I think for the limited uses in this file, we don't even need the do-while, as the code we're enclosing is not a single statement anyway. > +#endif > + > // ------ Input iterator requirements ------ > /** > * @brief Iterator preincrement > @@ -378,8 +386,10 @@ namespace __gnu_debug > _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(), > _M_message(__msg_bad_inc) > ._M_iterator(*this, "this")); > - __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); > - ++base(); > + _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_BEGIN { > + __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); > + ++base(); > + } _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_END; > return *this; > } > Yeah, I'll check if other operators need it, and if it's more than just the two places in my patch I'll go with that. If I don't get around to it (as I'm meant to have stopped work for the year yesterday) then feel free to do that.
diff --git a/libstdc++-v3/include/bits/c++config b/libstdc++-v3/include/bits/c++config index 284d24d933f..13d416845c3 100644 --- a/libstdc++-v3/include/bits/c++config +++ b/libstdc++-v3/include/bits/c++config @@ -565,15 +565,6 @@ namespace std # define _GLIBCXX_EXTERN_TEMPLATE -1 #endif - -#if _GLIBCXX_HAVE_IS_CONSTANT_EVALUATED -# define __glibcxx_constexpr_assert(cond) \ - if (std::__is_constant_evaluated() && !bool(cond)) \ - __builtin_unreachable() /* precondition violation detected! */ -#else -# define __glibcxx_constexpr_assert(unevaluated) -#endif - #undef _GLIBCXX_VERBOSE_ASSERT // Assert. diff --git a/libstdc++-v3/include/bits/stl_algobase.h b/libstdc++-v3/include/bits/stl_algobase.h index 01ca4496dfd..77d0ee7bcf5 100644 --- a/libstdc++-v3/include/bits/stl_algobase.h +++ b/libstdc++-v3/include/bits/stl_algobase.h @@ -318,6 +318,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __it; } template<typename _Ite, typename _Seq> + _GLIBCXX20_CONSTEXPR _Ite __niter_base(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, std::random_access_iterator_tag>&); @@ -545,6 +546,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER template<bool _IsMove, typename _Ite, typename _Seq, typename _Cat, typename _OI> + _GLIBCXX20_CONSTEXPR _OI __copy_move_a(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>&, const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>&, @@ -552,6 +554,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER template<bool _IsMove, typename _II, typename _Ite, typename _Seq, typename _Cat> + _GLIBCXX20_CONSTEXPR __gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat> __copy_move_a(_II, _II, const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>&); @@ -559,6 +562,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER template<bool _IsMove, typename _IIte, typename _ISeq, typename _ICat, typename _OIte, typename _OSeq, typename _OCat> + _GLIBCXX20_CONSTEXPR ::__gnu_debug::_Safe_iterator<_OIte, _OSeq, _OCat> __copy_move_a(const ::__gnu_debug::_Safe_iterator<_IIte, _ISeq, _ICat>&, const ::__gnu_debug::_Safe_iterator<_IIte, _ISeq, _ICat>&, @@ -812,6 +816,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER template<bool _IsMove, typename _Ite, typename _Seq, typename _Cat, typename _OI> + _GLIBCXX20_CONSTEXPR _OI __copy_move_backward_a( const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>&, @@ -820,6 +825,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER template<bool _IsMove, typename _II, typename _Ite, typename _Seq, typename _Cat> + _GLIBCXX20_CONSTEXPR __gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat> __copy_move_backward_a(_II, _II, const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>&); @@ -827,6 +833,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER template<bool _IsMove, typename _IIte, typename _ISeq, typename _ICat, typename _OIte, typename _OSeq, typename _OCat> + _GLIBCXX20_CONSTEXPR ::__gnu_debug::_Safe_iterator<_OIte, _OSeq, _OCat> __copy_move_backward_a( const ::__gnu_debug::_Safe_iterator<_IIte, _ISeq, _ICat>&, @@ -977,6 +984,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER { std::__fill_a1(__first, __last, __value); } template<typename _Ite, typename _Seq, typename _Cat, typename _Tp> + _GLIBCXX20_CONSTEXPR void __fill_a(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>&, const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>&, @@ -1082,6 +1090,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER template<typename _Ite, typename _Seq, typename _Cat, typename _Size, typename _Tp> + _GLIBCXX20_CONSTEXPR ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat> __fill_n_a(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>& __first, _Size __n, const _Tp& __value, @@ -1230,18 +1239,21 @@ _GLIBCXX_END_NAMESPACE_CONTAINER } template<typename _II1, typename _Seq1, typename _Cat1, typename _II2> + _GLIBCXX20_CONSTEXPR bool __equal_aux(const ::__gnu_debug::_Safe_iterator<_II1, _Seq1, _Cat1>&, const ::__gnu_debug::_Safe_iterator<_II1, _Seq1, _Cat1>&, _II2); template<typename _II1, typename _II2, typename _Seq2, typename _Cat2> + _GLIBCXX20_CONSTEXPR bool __equal_aux(_II1, _II1, const ::__gnu_debug::_Safe_iterator<_II2, _Seq2, _Cat2>&); template<typename _II1, typename _Seq1, typename _Cat1, typename _II2, typename _Seq2, typename _Cat2> + _GLIBCXX20_CONSTEXPR bool __equal_aux(const ::__gnu_debug::_Safe_iterator<_II1, _Seq1, _Cat1>&, const ::__gnu_debug::_Safe_iterator<_II1, _Seq1, _Cat1>&, @@ -1430,6 +1442,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER template<typename _Iter1, typename _Seq1, typename _Cat1, typename _II2> + _GLIBCXX20_CONSTEXPR bool __lexicographical_compare_aux( const ::__gnu_debug::_Safe_iterator<_Iter1, _Seq1, _Cat1>&, @@ -1438,6 +1451,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER template<typename _II1, typename _Iter2, typename _Seq2, typename _Cat2> + _GLIBCXX20_CONSTEXPR bool __lexicographical_compare_aux( _II1, _II1, @@ -1446,6 +1460,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER template<typename _Iter1, typename _Seq1, typename _Cat1, typename _Iter2, typename _Seq2, typename _Cat2> + _GLIBCXX20_CONSTEXPR bool __lexicographical_compare_aux( const ::__gnu_debug::_Safe_iterator<_Iter1, _Seq1, _Cat1>&, diff --git a/libstdc++-v3/include/debug/helper_functions.h b/libstdc++-v3/include/debug/helper_functions.h index 052b36b484c..4b76cb00f9a 100644 --- a/libstdc++-v3/include/debug/helper_functions.h +++ b/libstdc++-v3/include/debug/helper_functions.h @@ -324,6 +324,7 @@ namespace __gnu_debug /* Remove debug mode safe iterator layer, if any. */ template<typename _Iterator> + _GLIBCXX_CONSTEXPR inline _Iterator __unsafe(_Iterator __it) { return __it; } diff --git a/libstdc++-v3/include/debug/macros.h b/libstdc++-v3/include/debug/macros.h index 0fef0a006fc..4a3d0f2ea84 100644 --- a/libstdc++-v3/include/debug/macros.h +++ b/libstdc++-v3/include/debug/macros.h @@ -38,15 +38,12 @@ * the user error and where the error is reported. * */ -#define _GLIBCXX_DEBUG_VERIFY_COND_AT(_Cond,_ErrMsg,_File,_Line,_Func) \ - if (__builtin_expect(!bool(_Cond), false)) \ - __gnu_debug::_Error_formatter::_S_at(_File, _Line, _Func) \ - ._ErrMsg._M_error() #define _GLIBCXX_DEBUG_VERIFY_AT_F(_Cond,_ErrMsg,_File,_Line,_Func) \ do { \ - __glibcxx_constexpr_assert(_Cond); \ - _GLIBCXX_DEBUG_VERIFY_COND_AT(_Cond,_ErrMsg,_File,_Line,_Func); \ + if (__builtin_expect(!bool(_Cond), false)) \ + __gnu_debug::_Error_formatter::_S_at(_File, _Line, _Func) \ + ._ErrMsg._M_error(); \ } while (false) #define _GLIBCXX_DEBUG_VERIFY_AT(_Cond,_ErrMsg,_File,_Line) \ diff --git a/libstdc++-v3/include/debug/safe_base.h b/libstdc++-v3/include/debug/safe_base.h index 1dfa9f68b65..d9c17b52b48 100644 --- a/libstdc++-v3/include/debug/safe_base.h +++ b/libstdc++-v3/include/debug/safe_base.h @@ -75,6 +75,7 @@ namespace __gnu_debug protected: /** Initializes the iterator and makes it singular. */ + _GLIBCXX20_CONSTEXPR _Safe_iterator_base() : _M_sequence(0), _M_version(0), _M_prior(0), _M_next(0) { } @@ -86,18 +87,31 @@ namespace __gnu_debug * singular. Otherwise, the iterator will reference @p __seq and * be nonsingular. */ + _GLIBCXX20_CONSTEXPR _Safe_iterator_base(const _Safe_sequence_base* __seq, bool __constant) : _M_sequence(0), _M_version(0), _M_prior(0), _M_next(0) - { this->_M_attach(const_cast<_Safe_sequence_base*>(__seq), __constant); } + { + if (!std::__is_constant_evaluated()) + this->_M_attach(const_cast<_Safe_sequence_base*>(__seq), __constant); + } /** Initializes the iterator to reference the same sequence that @p __x does. @p __constant is true if this is a constant iterator, and false if it is mutable. */ + _GLIBCXX20_CONSTEXPR _Safe_iterator_base(const _Safe_iterator_base& __x, bool __constant) : _M_sequence(0), _M_version(0), _M_prior(0), _M_next(0) - { this->_M_attach(__x._M_sequence, __constant); } + { + if (!std::__is_constant_evaluated()) + this->_M_attach(__x._M_sequence, __constant); + } - ~_Safe_iterator_base() { this->_M_detach(); } + _GLIBCXX20_CONSTEXPR + ~_Safe_iterator_base() + { + if (!std::__is_constant_evaluated()) + this->_M_detach(); + } /** For use in _Safe_iterator. */ __gnu_cxx::__mutex& @@ -201,24 +215,34 @@ namespace __gnu_debug protected: // Initialize with a version number of 1 and no iterators + _GLIBCXX20_CONSTEXPR _Safe_sequence_base() _GLIBCXX_NOEXCEPT : _M_iterators(0), _M_const_iterators(0), _M_version(1) { } #if __cplusplus >= 201103L + _GLIBCXX20_CONSTEXPR _Safe_sequence_base(const _Safe_sequence_base&) noexcept : _Safe_sequence_base() { } // Move constructor swap iterators. + _GLIBCXX20_CONSTEXPR _Safe_sequence_base(_Safe_sequence_base&& __seq) noexcept : _Safe_sequence_base() - { _M_swap(__seq); } + { + if (!std::__is_constant_evaluated()) + _M_swap(__seq); + } #endif /** Notify all iterators that reference this sequence that the sequence is being destroyed. */ + _GLIBCXX20_CONSTEXPR ~_Safe_sequence_base() - { this->_M_detach_all(); } + { + if (!std::__is_constant_evaluated()) + this->_M_detach_all(); + } /** Detach all iterators, leaving them singular. */ void @@ -244,6 +268,7 @@ namespace __gnu_debug * operation is complete all iterators that originally referenced * one container now reference the other container. */ + _GLIBCXX20_CONSTEXPR void _M_swap(_Safe_sequence_base& __x) _GLIBCXX_USE_NOEXCEPT; diff --git a/libstdc++-v3/include/debug/safe_container.h b/libstdc++-v3/include/debug/safe_container.h index 0d8f64740b0..636156af9f5 100644 --- a/libstdc++-v3/include/debug/safe_container.h +++ b/libstdc++-v3/include/debug/safe_container.h @@ -43,6 +43,7 @@ namespace __gnu_debug { typedef _SafeBase<_SafeContainer> _Base; + _GLIBCXX20_CONSTEXPR _SafeContainer& _M_cont() _GLIBCXX_NOEXCEPT { return *static_cast<_SafeContainer*>(this); } @@ -54,20 +55,23 @@ namespace __gnu_debug _Safe_container(_Safe_container&&) = default; private: + _GLIBCXX20_CONSTEXPR _Safe_container(_Safe_container&& __x, const _Alloc&, std::true_type) : _Safe_container(std::move(__x)) { } + _GLIBCXX20_CONSTEXPR _Safe_container(_Safe_container&& __x, const _Alloc& __a, std::false_type) : _Safe_container() { if (__x._M_cont().get_allocator() == __a) _Base::_M_swap(__x); - else + else if (!std::__is_constant_evaluated()) __x._M_invalidate_all(); } protected: + _GLIBCXX20_CONSTEXPR _Safe_container(_Safe_container&& __x, const _Alloc& __a) : _Safe_container(std::move(__x), __a, typename std::allocator_traits<_Alloc>::is_always_equal{}) @@ -75,17 +79,23 @@ namespace __gnu_debug #endif // Copy assignment invalidate all iterators. + _GLIBCXX20_CONSTEXPR _Safe_container& operator=(const _Safe_container&) _GLIBCXX_NOEXCEPT { - this->_M_invalidate_all(); + if (!std::__is_constant_evaluated()) + this->_M_invalidate_all(); return *this; } #if __cplusplus >= 201103L + _GLIBCXX20_CONSTEXPR _Safe_container& operator=(_Safe_container&& __x) noexcept { + if (std::__is_constant_evaluated()) + return *this; + if (std::__addressof(__x) == this) { // Standard containers have a valid but unspecified value after @@ -113,6 +123,7 @@ namespace __gnu_debug return *this; } + _GLIBCXX20_CONSTEXPR void _M_swap(_Safe_container& __x) noexcept { diff --git a/libstdc++-v3/include/debug/safe_iterator.h b/libstdc++-v3/include/debug/safe_iterator.h index 693192b3ea9..26f008982f8 100644 --- a/libstdc++-v3/include/debug/safe_iterator.h +++ b/libstdc++-v3/include/debug/safe_iterator.h @@ -40,6 +40,7 @@ #endif #define _GLIBCXX_DEBUG_VERIFY_OPERANDS(_Lhs, _Rhs, _BadMsgId, _DiffMsgId) \ + if (!std::__is_constant_evaluated()) { \ _GLIBCXX_DEBUG_VERIFY((!_Lhs._M_singular() && !_Rhs._M_singular()) \ || (_Lhs._M_value_initialized() \ && _Rhs._M_value_initialized()), \ @@ -49,7 +50,8 @@ _GLIBCXX_DEBUG_VERIFY(_Lhs._M_can_compare(_Rhs), \ _M_message(_DiffMsgId) \ ._M_iterator(_Lhs, #_Lhs) \ - ._M_iterator(_Rhs, #_Rhs)) + ._M_iterator(_Rhs, #_Rhs)); \ + } #define _GLIBCXX_DEBUG_VERIFY_EQ_OPERANDS(_Lhs, _Rhs) \ _GLIBCXX_DEBUG_VERIFY_OPERANDS(_Lhs, _Rhs, __msg_iter_compare_bad, \ @@ -131,9 +133,13 @@ namespace __gnu_debug struct _Unchecked { }; + _GLIBCXX20_CONSTEXPR _Safe_iterator(const _Safe_iterator& __x, _Unchecked) _GLIBCXX_NOEXCEPT : _Iter_base(__x.base()), _Safe_base() - { _M_attach(__x._M_sequence); } + { + if (!std::__is_constant_evaluated()) + _M_attach(__x._M_sequence); + } public: typedef _Iterator iterator_type; @@ -148,6 +154,7 @@ namespace __gnu_debug #endif /// @post the iterator is singular and unattached + _GLIBCXX20_CONSTEXPR _Safe_iterator() _GLIBCXX_NOEXCEPT : _Iter_base() { } /** @@ -157,6 +164,7 @@ namespace __gnu_debug * @pre @p seq is not NULL * @post this is not singular */ + _GLIBCXX20_CONSTEXPR _Safe_iterator(_Iterator __i, const _Safe_sequence_base* __seq) _GLIBCXX_NOEXCEPT : _Iter_base(__i), _Safe_base(__seq, _S_constant()) @@ -165,9 +173,13 @@ namespace __gnu_debug /** * @brief Copy construction. */ + _GLIBCXX20_CONSTEXPR _Safe_iterator(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT : _Iter_base(__x.base()), _Safe_base() { + if (std::__is_constant_evaluated()) + return; + // _GLIBCXX_RESOLVE_LIB_DEFECTS // DR 408. Is vector<reverse_iterator<char*> > forbidden? _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() @@ -183,9 +195,16 @@ namespace __gnu_debug * @brief Move construction. * @post __x is singular and unattached */ + _GLIBCXX20_CONSTEXPR _Safe_iterator(_Safe_iterator&& __x) noexcept : _Iter_base() { + if (std::__is_constant_evaluated()) + { + base() = __x.base(); + return; + } + _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() || __x._M_value_initialized(), _M_message(__msg_init_copy_singular) @@ -203,6 +222,7 @@ namespace __gnu_debug * constant iterator. */ template<typename _MutableIterator> + _GLIBCXX20_CONSTEXPR _Safe_iterator( const _Safe_iterator<_MutableIterator, _Sequence, typename __gnu_cxx::__enable_if<_IsConstant::__value && @@ -211,6 +231,9 @@ namespace __gnu_debug _GLIBCXX_NOEXCEPT : _Iter_base(__x.base()) { + if (std::__is_constant_evaluated()) + return; + // _GLIBCXX_RESOLVE_LIB_DEFECTS // DR 408. Is vector<reverse_iterator<char*> > forbidden? _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() @@ -224,9 +247,16 @@ namespace __gnu_debug /** * @brief Copy assignment. */ + _GLIBCXX20_CONSTEXPR _Safe_iterator& operator=(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT { + if (std::__is_constant_evaluated()) + { + base() = __x.base(); + return *this; + } + // _GLIBCXX_RESOLVE_LIB_DEFECTS // DR 408. Is vector<reverse_iterator<char*> > forbidden? _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() @@ -256,9 +286,16 @@ namespace __gnu_debug * @brief Move assignment. * @post __x is singular and unattached */ + _GLIBCXX20_CONSTEXPR _Safe_iterator& operator=(_Safe_iterator&& __x) noexcept { + if (std::__is_constant_evaluated()) + { + base() = __x.base(); + return *this; + } + _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() || __x._M_value_initialized(), _M_message(__msg_copy_singular) @@ -292,12 +329,16 @@ namespace __gnu_debug * @pre iterator is dereferenceable */ _GLIBCXX_NODISCARD + _GLIBCXX20_CONSTEXPR reference operator*() const _GLIBCXX_NOEXCEPT { - _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(), - _M_message(__msg_bad_deref) - ._M_iterator(*this, "this")); + if (!std::__is_constant_evaluated()) + { + _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(), + _M_message(__msg_bad_deref) + ._M_iterator(*this, "this")); + } return *base(); } @@ -306,12 +347,16 @@ namespace __gnu_debug * @pre iterator is dereferenceable */ _GLIBCXX_NODISCARD + _GLIBCXX20_CONSTEXPR pointer operator->() const _GLIBCXX_NOEXCEPT { - _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(), - _M_message(__msg_bad_deref) - ._M_iterator(*this, "this")); + if (!std::__is_constant_evaluated()) + { + _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(), + _M_message(__msg_bad_deref) + ._M_iterator(*this, "this")); + } return base().operator->(); } @@ -320,9 +365,16 @@ namespace __gnu_debug * @brief Iterator preincrement * @pre iterator is incrementable */ + _GLIBCXX20_CONSTEXPR _Safe_iterator& operator++() _GLIBCXX_NOEXCEPT { + if (std::__is_constant_evaluated()) + { + ++base(); + return *this; + } + _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(), _M_message(__msg_bad_inc) ._M_iterator(*this, "this")); @@ -335,12 +387,16 @@ namespace __gnu_debug * @brief Iterator postincrement * @pre iterator is incrementable */ + _GLIBCXX20_CONSTEXPR _Safe_iterator operator++(int) _GLIBCXX_NOEXCEPT { - _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(), - _M_message(__msg_bad_inc) - ._M_iterator(*this, "this")); + if (!std::__is_constant_evaluated()) + { + _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(), + _M_message(__msg_bad_inc) + ._M_iterator(*this, "this")); + } _Safe_iterator __ret(*this, _Unchecked()); ++*this; return __ret; @@ -356,9 +412,11 @@ namespace __gnu_debug /** * @brief Return the underlying iterator */ + _GLIBCXX20_CONSTEXPR _Iterator& base() _GLIBCXX_NOEXCEPT { return *this; } + _GLIBCXX20_CONSTEXPR const _Iterator& base() const _GLIBCXX_NOEXCEPT { return *this; } @@ -366,6 +424,7 @@ namespace __gnu_debug * @brief Conversion to underlying non-debug iterator to allow * better interaction with non-debug containers. */ + _GLIBCXX20_CONSTEXPR operator _Iterator() const _GLIBCXX_NOEXCEPT { return *this; } /** Attach iterator to the given sequence. */ @@ -440,6 +499,7 @@ namespace __gnu_debug _M_get_distance_to_end() const; /// Is this iterator equal to the sequence's begin() iterator? + _GLIBCXX20_CONSTEXPR bool _M_is_begin() const { return base() == _M_get_sequence()->_M_base().begin(); } @@ -466,6 +526,7 @@ namespace __gnu_debug typedef _Safe_iterator<_Iterator, _Sequence, iterator_category> _Self; _GLIBCXX_NODISCARD + _GLIBCXX20_CONSTEXPR friend bool operator==(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT { @@ -475,6 +536,7 @@ namespace __gnu_debug template<typename _IteR> _GLIBCXX_NODISCARD + _GLIBCXX20_CONSTEXPR friend bool operator==(const _Self& __lhs, const _Safe_iterator<_IteR, _Sequence, iterator_category>& __rhs) @@ -518,6 +580,7 @@ namespace __gnu_debug typedef typename _Safe_base::_Unchecked _Unchecked; + _GLIBCXX20_CONSTEXPR _Safe_iterator(const _Safe_iterator& __x, _Unchecked __unchecked) _GLIBCXX_NOEXCEPT : _Safe_base(__x, __unchecked) @@ -525,6 +588,7 @@ namespace __gnu_debug public: /// @post the iterator is singular and unattached + _GLIBCXX20_CONSTEXPR _Safe_iterator() _GLIBCXX_NOEXCEPT { } /** @@ -534,6 +598,7 @@ namespace __gnu_debug * @pre @p seq is not NULL * @post this is not singular */ + _GLIBCXX20_CONSTEXPR _Safe_iterator(_Iterator __i, const _Safe_sequence_base* __seq) _GLIBCXX_NOEXCEPT : _Safe_base(__i, __seq) @@ -542,12 +607,14 @@ namespace __gnu_debug /** * @brief Copy construction. */ + _GLIBCXX20_CONSTEXPR _Safe_iterator(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT : _Safe_base(__x) { } #if __cplusplus >= 201103L /** @brief Move construction. */ + _GLIBCXX20_CONSTEXPR _Safe_iterator(_Safe_iterator&&) = default; #endif @@ -556,6 +623,7 @@ namespace __gnu_debug * constant iterator. */ template<typename _MutableIterator> + _GLIBCXX20_CONSTEXPR _Safe_iterator( const _Safe_iterator<_MutableIterator, _Sequence, typename __gnu_cxx::__enable_if<_Safe_base::_IsConstant::__value && @@ -588,6 +656,7 @@ namespace __gnu_debug * @brief Iterator preincrement * @pre iterator is incrementable */ + _GLIBCXX20_CONSTEXPR _Safe_iterator& operator++() _GLIBCXX_NOEXCEPT { @@ -615,9 +684,16 @@ namespace __gnu_debug * @brief Iterator predecrement * @pre iterator is decrementable */ + _GLIBCXX20_CONSTEXPR _Safe_iterator& operator--() _GLIBCXX_NOEXCEPT { + if (std::__is_constant_evaluated()) + { + --this->base(); + return *this; + } + _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(), _M_message(__msg_bad_dec) ._M_iterator(*this, "this")); @@ -663,6 +739,8 @@ namespace __gnu_debug std::random_access_iterator_tag> _OtherSelf; typedef typename _Safe_base::_Unchecked _Unchecked; + + _GLIBCXX20_CONSTEXPR _Safe_iterator(const _Safe_iterator& __x, _Unchecked __unchecked) _GLIBCXX_NOEXCEPT : _Safe_base(__x, __unchecked) @@ -673,6 +751,7 @@ namespace __gnu_debug typedef typename _Safe_base::reference reference; /// @post the iterator is singular and unattached + _GLIBCXX20_CONSTEXPR _Safe_iterator() _GLIBCXX_NOEXCEPT { } /** @@ -682,6 +761,7 @@ namespace __gnu_debug * @pre @p seq is not NULL * @post this is not singular */ + _GLIBCXX20_CONSTEXPR _Safe_iterator(_Iterator __i, const _Safe_sequence_base* __seq) _GLIBCXX_NOEXCEPT : _Safe_base(__i, __seq) @@ -690,6 +770,7 @@ namespace __gnu_debug /** * @brief Copy construction. */ + _GLIBCXX20_CONSTEXPR _Safe_iterator(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT : _Safe_base(__x) { } @@ -704,6 +785,7 @@ namespace __gnu_debug * constant iterator. */ template<typename _MutableIterator> + _GLIBCXX20_CONSTEXPR _Safe_iterator( const _Safe_iterator<_MutableIterator, _Sequence, typename __gnu_cxx::__enable_if<_Safe_base::_IsConstant::__value && @@ -742,6 +824,7 @@ namespace __gnu_debug * @brief Iterator preincrement * @pre iterator is incrementable */ + _GLIBCXX20_CONSTEXPR _Safe_iterator& operator++() _GLIBCXX_NOEXCEPT { @@ -753,12 +836,16 @@ namespace __gnu_debug * @brief Iterator postincrement * @pre iterator is incrementable */ + _GLIBCXX20_CONSTEXPR _Safe_iterator operator++(int) _GLIBCXX_NOEXCEPT { - _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(), - _M_message(__msg_bad_inc) - ._M_iterator(*this, "this")); + if (!std::__is_constant_evaluated()) + { + _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(), + _M_message(__msg_bad_inc) + ._M_iterator(*this, "this")); + } _Safe_iterator __ret(*this, _Unchecked()); ++*this; return __ret; @@ -769,6 +856,7 @@ namespace __gnu_debug * @brief Iterator predecrement * @pre iterator is decrementable */ + _GLIBCXX20_CONSTEXPR _Safe_iterator& operator--() _GLIBCXX_NOEXCEPT { @@ -780,12 +868,16 @@ namespace __gnu_debug * @brief Iterator postdecrement * @pre iterator is decrementable */ + _GLIBCXX20_CONSTEXPR _Safe_iterator operator--(int) _GLIBCXX_NOEXCEPT { - _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(), - _M_message(__msg_bad_dec) - ._M_iterator(*this, "this")); + if (!std::__is_constant_evaluated()) + { + _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(), + _M_message(__msg_bad_dec) + ._M_iterator(*this, "this")); + } _Safe_iterator __ret(*this, _Unchecked()); --*this; return __ret; @@ -793,19 +885,30 @@ namespace __gnu_debug // ------ Random access iterator requirements ------ _GLIBCXX_NODISCARD + _GLIBCXX20_CONSTEXPR reference operator[](difference_type __n) const _GLIBCXX_NOEXCEPT { - _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n) - && this->_M_can_advance(__n + 1), - _M_message(__msg_iter_subscript_oob) - ._M_iterator(*this)._M_integer(__n)); + if (!std::__is_constant_evaluated()) + { + _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n) + && this->_M_can_advance(__n + 1), + _M_message(__msg_iter_subscript_oob) + ._M_iterator(*this)._M_integer(__n)); + } return this->base()[__n]; } + _GLIBCXX20_CONSTEXPR _Safe_iterator& operator+=(difference_type __n) _GLIBCXX_NOEXCEPT { + if (std::__is_constant_evaluated()) + { + this->base() += __n; + return *this; + } + _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n), _M_message(__msg_advance_oob) ._M_iterator(*this)._M_integer(__n)); @@ -814,9 +917,16 @@ namespace __gnu_debug return *this; } + _GLIBCXX20_CONSTEXPR _Safe_iterator& operator-=(difference_type __n) _GLIBCXX_NOEXCEPT { + if (std::__is_constant_evaluated()) + { + this->base() -= __n; + return *this; + } + _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(-__n), _M_message(__msg_retreat_oob) ._M_iterator(*this)._M_integer(__n)); @@ -827,6 +937,7 @@ namespace __gnu_debug #if __cpp_lib_three_way_comparison [[nodiscard]] + _GLIBCXX20_CONSTEXPR friend auto operator<=>(const _Self& __lhs, const _Self& __rhs) noexcept { @@ -835,6 +946,7 @@ namespace __gnu_debug } [[nodiscard]] + _GLIBCXX20_CONSTEXPR friend auto operator<=>(const _Self& __lhs, const _OtherSelf& __rhs) noexcept { @@ -912,6 +1024,7 @@ namespace __gnu_debug // operators but also operator- must accept mixed iterator/const_iterator // parameters. _GLIBCXX_NODISCARD + _GLIBCXX20_CONSTEXPR friend difference_type operator-(const _Self& __lhs, const _OtherSelf& __rhs) _GLIBCXX_NOEXCEPT { @@ -920,6 +1033,7 @@ namespace __gnu_debug } _GLIBCXX_NODISCARD + _GLIBCXX20_CONSTEXPR friend difference_type operator-(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT { @@ -928,32 +1042,44 @@ namespace __gnu_debug } _GLIBCXX_NODISCARD + _GLIBCXX20_CONSTEXPR friend _Self operator+(const _Self& __x, difference_type __n) _GLIBCXX_NOEXCEPT { - _GLIBCXX_DEBUG_VERIFY(__x._M_can_advance(__n), - _M_message(__msg_advance_oob) - ._M_iterator(__x)._M_integer(__n)); + if (!std::__is_constant_evaluated()) + { + _GLIBCXX_DEBUG_VERIFY(__x._M_can_advance(__n), + _M_message(__msg_advance_oob) + ._M_iterator(__x)._M_integer(__n)); + } return _Safe_iterator(__x.base() + __n, __x._M_sequence); } _GLIBCXX_NODISCARD + _GLIBCXX20_CONSTEXPR friend _Self operator+(difference_type __n, const _Self& __x) _GLIBCXX_NOEXCEPT { - _GLIBCXX_DEBUG_VERIFY(__x._M_can_advance(__n), - _M_message(__msg_advance_oob) - ._M_iterator(__x)._M_integer(__n)); + if (!std::__is_constant_evaluated()) + { + _GLIBCXX_DEBUG_VERIFY(__x._M_can_advance(__n), + _M_message(__msg_advance_oob) + ._M_iterator(__x)._M_integer(__n)); + } return _Safe_iterator(__n + __x.base(), __x._M_sequence); } _GLIBCXX_NODISCARD + _GLIBCXX20_CONSTEXPR friend _Self operator-(const _Self& __x, difference_type __n) _GLIBCXX_NOEXCEPT { - _GLIBCXX_DEBUG_VERIFY(__x._M_can_advance(-__n), - _M_message(__msg_retreat_oob) - ._M_iterator(__x)._M_integer(__n)); + if (!std::__is_constant_evaluated()) + { + _GLIBCXX_DEBUG_VERIFY(__x._M_can_advance(-__n), + _M_message(__msg_retreat_oob) + ._M_iterator(__x)._M_integer(__n)); + } return _Safe_iterator(__x.base() - __n, __x._M_sequence); } }; diff --git a/libstdc++-v3/include/debug/safe_iterator.tcc b/libstdc++-v3/include/debug/safe_iterator.tcc index 170229ad2f1..0bb3dd017b9 100644 --- a/libstdc++-v3/include/debug/safe_iterator.tcc +++ b/libstdc++-v3/include/debug/safe_iterator.tcc @@ -236,6 +236,7 @@ namespace std _GLIBCXX_VISIBILITY(default) _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Ite, typename _Seq> + _GLIBCXX20_CONSTEXPR _Ite __niter_base(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, std::random_access_iterator_tag>& __it) @@ -243,6 +244,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<bool _IsMove, typename _Ite, typename _Seq, typename _Cat, typename _OI> + _GLIBCXX20_CONSTEXPR _OI __copy_move_a( const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>& __first, @@ -262,6 +264,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<bool _IsMove, typename _II, typename _Ite, typename _Seq, typename _Cat> + _GLIBCXX20_CONSTEXPR __gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat> __copy_move_a(_II __first, _II __last, const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>& __result) @@ -282,6 +285,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<bool _IsMove, typename _IIte, typename _ISeq, typename _ICat, typename _OIte, typename _OSeq, typename _OCat> + _GLIBCXX20_CONSTEXPR ::__gnu_debug::_Safe_iterator<_OIte, _OSeq, _OCat> __copy_move_a( const ::__gnu_debug::_Safe_iterator<_IIte, _ISeq, _ICat>& __first, @@ -310,6 +314,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<bool _IsMove, typename _Ite, typename _Seq, typename _Cat, typename _OI> + _GLIBCXX20_CONSTEXPR _OI __copy_move_backward_a( const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>& __first, @@ -329,6 +334,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<bool _IsMove, typename _II, typename _Ite, typename _Seq, typename _Cat> + _GLIBCXX20_CONSTEXPR __gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat> __copy_move_backward_a(_II __first, _II __last, const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>& __result) @@ -350,6 +356,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<bool _IsMove, typename _IIte, typename _ISeq, typename _ICat, typename _OIte, typename _OSeq, typename _OCat> + _GLIBCXX20_CONSTEXPR ::__gnu_debug::_Safe_iterator<_OIte, _OSeq, _OCat> __copy_move_backward_a( const ::__gnu_debug::_Safe_iterator<_IIte, _ISeq, _ICat>& __first, @@ -377,6 +384,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template<typename _Ite, typename _Seq, typename _Cat, typename _Tp> + _GLIBCXX20_CONSTEXPR void __fill_a(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>& __first, const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>& __last, @@ -393,6 +401,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Ite, typename _Seq, typename _Cat, typename _Size, typename _Tp> + _GLIBCXX20_CONSTEXPR ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat> __fill_n_a(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>& __first, _Size __n, const _Tp& __value, @@ -415,6 +424,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template<typename _II1, typename _Seq1, typename _Cat1, typename _II2> + _GLIBCXX20_CONSTEXPR bool __equal_aux( const ::__gnu_debug::_Safe_iterator<_II1, _Seq1, _Cat1>& __first1, @@ -432,6 +442,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template<typename _II1, typename _II2, typename _Seq2, typename _Cat2> + _GLIBCXX20_CONSTEXPR bool __equal_aux(_II1 __first1, _II1 __last1, const ::__gnu_debug::_Safe_iterator<_II2, _Seq2, _Cat2>& __first2) @@ -449,6 +460,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _II1, typename _Seq1, typename _Cat1, typename _II2, typename _Seq2, typename _Cat2> + _GLIBCXX20_CONSTEXPR bool __equal_aux( const ::__gnu_debug::_Safe_iterator<_II1, _Seq1, _Cat1>& __first1, @@ -473,6 +485,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Ite1, typename _Seq1, typename _Cat1, typename _II2> + _GLIBCXX20_CONSTEXPR bool __lexicographical_compare_aux( const ::__gnu_debug::_Safe_iterator<_Ite1, _Seq1, _Cat1>& __first1, @@ -493,6 +506,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _II1, typename _Ite2, typename _Seq2, typename _Cat2> + _GLIBCXX20_CONSTEXPR bool __lexicographical_compare_aux( _II1 __first1, _II1 __last1, @@ -513,6 +527,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Ite1, typename _Seq1, typename _Cat1, typename _Ite2, typename _Seq2, typename _Cat2> + _GLIBCXX20_CONSTEXPR bool __lexicographical_compare_aux( const ::__gnu_debug::_Safe_iterator<_Ite1, _Seq1, _Cat1>& __first1, diff --git a/libstdc++-v3/include/debug/vector b/libstdc++-v3/include/debug/vector index ed462caf936..124ae6da1c1 100644 --- a/libstdc++-v3/include/debug/vector +++ b/libstdc++-v3/include/debug/vector @@ -55,22 +55,27 @@ namespace __gnu_debug { typedef typename _BaseSequence::size_type size_type; + _GLIBCXX20_CONSTEXPR const _SafeSequence& _M_seq() const { return *static_cast<const _SafeSequence*>(this); } protected: + _GLIBCXX20_CONSTEXPR _Safe_vector() _GLIBCXX_NOEXCEPT : _M_guaranteed_capacity(0) { _M_update_guaranteed_capacity(); } + _GLIBCXX20_CONSTEXPR _Safe_vector(const _Safe_vector&) _GLIBCXX_NOEXCEPT : _M_guaranteed_capacity(0) { _M_update_guaranteed_capacity(); } + _GLIBCXX20_CONSTEXPR _Safe_vector(size_type __n) _GLIBCXX_NOEXCEPT : _M_guaranteed_capacity(__n) { } + _GLIBCXX20_CONSTEXPR _Safe_vector& operator=(const _Safe_vector&) _GLIBCXX_NOEXCEPT { @@ -79,10 +84,12 @@ namespace __gnu_debug } #if __cplusplus >= 201103L + _GLIBCXX20_CONSTEXPR _Safe_vector(_Safe_vector&& __x) noexcept : _Safe_vector() { __x._M_guaranteed_capacity = 0; } + _GLIBCXX20_CONSTEXPR _Safe_vector& operator=(_Safe_vector&& __x) noexcept { @@ -98,6 +105,7 @@ namespace __gnu_debug _M_requires_reallocation(size_type __elements) const _GLIBCXX_NOEXCEPT { return __elements > _M_seq().capacity(); } + _GLIBCXX20_CONSTEXPR void _M_update_guaranteed_capacity() _GLIBCXX_NOEXCEPT { @@ -172,15 +180,18 @@ namespace __debug vector() = default; #endif + _GLIBCXX20_CONSTEXPR explicit vector(const _Allocator& __a) _GLIBCXX_NOEXCEPT : _Base(__a) { } #if __cplusplus >= 201103L + _GLIBCXX20_CONSTEXPR explicit vector(size_type __n, const _Allocator& __a = _Allocator()) : _Base(__n, __a), _Safe_vector(__n) { } + _GLIBCXX20_CONSTEXPR vector(size_type __n, const __type_identity_t<_Tp>& __value, const _Allocator& __a = _Allocator()) : _Base(__n, __value, __a) { } @@ -197,10 +208,11 @@ namespace __debug #else template<class _InputIterator> #endif + _GLIBCXX20_CONSTEXPR vector(_InputIterator __first, _InputIterator __last, const _Allocator& __a = _Allocator()) - : _Base(__gnu_debug::__base( - __glibcxx_check_valid_constructor_range(__first, __last)), + : _Base(__gnu_debug::__base(std::__is_constant_evaluated() ? __first + : __glibcxx_check_valid_constructor_range(__first, __last)), __gnu_debug::__base(__last), __a) { } #if __cplusplus < 201103L @@ -212,9 +224,11 @@ namespace __debug vector(const vector&) = default; vector(vector&&) = default; + _GLIBCXX20_CONSTEXPR vector(const vector& __x, const __type_identity_t<allocator_type>& __a) : _Base(__x, __a) { } + _GLIBCXX20_CONSTEXPR vector(vector&& __x, const __type_identity_t<allocator_type>& __a) noexcept( std::is_nothrow_constructible<_Base, @@ -223,6 +237,7 @@ namespace __debug _Base(std::move(__x), __a), _Safe_vector(std::move(__x)) { } + _GLIBCXX20_CONSTEXPR vector(initializer_list<value_type> __l, const allocator_type& __a = allocator_type()) : _Base(__l, __a) { } @@ -231,6 +246,7 @@ namespace __debug #endif /// Construction from a normal-mode vector + _GLIBCXX20_CONSTEXPR vector(_Base_ref __x) : _Base(__x._M_ref) { } @@ -241,12 +257,16 @@ namespace __debug vector& operator=(vector&&) = default; + _GLIBCXX20_CONSTEXPR vector& operator=(initializer_list<value_type> __l) { _Base::operator=(__l); - this->_M_invalidate_all(); - this->_M_update_guaranteed_capacity(); + if (!std::__is_constant_evaluated()) + { + this->_M_invalidate_all(); + this->_M_update_guaranteed_capacity(); + } return *this; } #endif @@ -257,9 +277,14 @@ namespace __debug #else template<typename _InputIterator> #endif + _GLIBCXX20_CONSTEXPR void assign(_InputIterator __first, _InputIterator __last) { + if (std::__is_constant_evaluated()) + return _Base::assign(__gnu_debug::__unsafe(__first), + __gnu_debug::__unsafe(__last)); + typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist; __glibcxx_check_valid_range2(__first, __last, __dist); @@ -273,21 +298,29 @@ namespace __debug this->_M_update_guaranteed_capacity(); } + _GLIBCXX20_CONSTEXPR void assign(size_type __n, const _Tp& __u) { _Base::assign(__n, __u); - this->_M_invalidate_all(); - this->_M_update_guaranteed_capacity(); + if (!std::__is_constant_evaluated()) + { + this->_M_invalidate_all(); + this->_M_update_guaranteed_capacity(); + } } #if __cplusplus >= 201103L + _GLIBCXX20_CONSTEXPR void assign(initializer_list<value_type> __l) { _Base::assign(__l); - this->_M_invalidate_all(); - this->_M_update_guaranteed_capacity(); + if (!std::__is_constant_evaluated()) + { + this->_M_invalidate_all(); + this->_M_update_guaranteed_capacity(); + } } #endif @@ -295,62 +328,74 @@ namespace __debug // iterators: _GLIBCXX_NODISCARD + _GLIBCXX20_CONSTEXPR iterator begin() _GLIBCXX_NOEXCEPT { return iterator(_Base::begin(), this); } _GLIBCXX_NODISCARD + _GLIBCXX20_CONSTEXPR const_iterator begin() const _GLIBCXX_NOEXCEPT { return const_iterator(_Base::begin(), this); } _GLIBCXX_NODISCARD + _GLIBCXX20_CONSTEXPR iterator end() _GLIBCXX_NOEXCEPT { return iterator(_Base::end(), this); } _GLIBCXX_NODISCARD + _GLIBCXX20_CONSTEXPR const_iterator end() const _GLIBCXX_NOEXCEPT { return const_iterator(_Base::end(), this); } _GLIBCXX_NODISCARD + _GLIBCXX20_CONSTEXPR reverse_iterator rbegin() _GLIBCXX_NOEXCEPT { return reverse_iterator(end()); } _GLIBCXX_NODISCARD + _GLIBCXX20_CONSTEXPR const_reverse_iterator rbegin() const _GLIBCXX_NOEXCEPT { return const_reverse_iterator(end()); } _GLIBCXX_NODISCARD + _GLIBCXX20_CONSTEXPR reverse_iterator rend() _GLIBCXX_NOEXCEPT { return reverse_iterator(begin()); } _GLIBCXX_NODISCARD + _GLIBCXX20_CONSTEXPR const_reverse_iterator rend() const _GLIBCXX_NOEXCEPT { return const_reverse_iterator(begin()); } #if __cplusplus >= 201103L [[__nodiscard__]] + _GLIBCXX20_CONSTEXPR const_iterator cbegin() const noexcept { return const_iterator(_Base::begin(), this); } [[__nodiscard__]] + _GLIBCXX20_CONSTEXPR const_iterator cend() const noexcept { return const_iterator(_Base::end(), this); } [[__nodiscard__]] + _GLIBCXX20_CONSTEXPR const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(end()); } [[__nodiscard__]] + _GLIBCXX20_CONSTEXPR const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); } @@ -361,9 +406,13 @@ namespace __debug using _Base::max_size; #if __cplusplus >= 201103L + _GLIBCXX20_CONSTEXPR void resize(size_type __sz) { + if (std::__is_constant_evaluated()) + return _Base::resize(__sz); + bool __realloc = this->_M_requires_reallocation(__sz); if (__sz < this->size()) this->_M_invalidate_after_nth(__sz); @@ -373,9 +422,13 @@ namespace __debug this->_M_update_guaranteed_capacity(); } + _GLIBCXX20_CONSTEXPR void resize(size_type __sz, const _Tp& __c) { + if (std::__is_constant_evaluated()) + return _Base::resize(__sz, __c); + bool __realloc = this->_M_requires_reallocation(__sz); if (__sz < this->size()) this->_M_invalidate_after_nth(__sz); @@ -399,9 +452,13 @@ namespace __debug #endif #if __cplusplus >= 201103L + _GLIBCXX20_CONSTEXPR void shrink_to_fit() { + if (std::__is_constant_evaluated()) + return _Base::shrink_to_fit(); + if (_Base::_M_shrink_to_fit()) { this->_M_guaranteed_capacity = _Base::capacity(); @@ -411,9 +468,13 @@ namespace __debug #endif _GLIBCXX_NODISCARD + _GLIBCXX20_CONSTEXPR size_type capacity() const _GLIBCXX_NOEXCEPT { + if (std::__is_constant_evaluated()) + return _Base::capacity(); + #ifdef _GLIBCXX_DEBUG_PEDANTIC return this->_M_guaranteed_capacity; #else @@ -423,9 +484,13 @@ namespace __debug using _Base::empty; + _GLIBCXX20_CONSTEXPR void reserve(size_type __n) { + if (std::__is_constant_evaluated()) + return _Base::reserve(__n); + bool __realloc = this->_M_requires_reallocation(__n); _Base::reserve(__n); if (__n > this->_M_guaranteed_capacity) @@ -436,6 +501,7 @@ namespace __debug // element access: _GLIBCXX_NODISCARD + _GLIBCXX20_CONSTEXPR reference operator[](size_type __n) _GLIBCXX_NOEXCEPT { @@ -444,6 +510,7 @@ namespace __debug } _GLIBCXX_NODISCARD + _GLIBCXX20_CONSTEXPR const_reference operator[](size_type __n) const _GLIBCXX_NOEXCEPT { @@ -454,6 +521,7 @@ namespace __debug using _Base::at; _GLIBCXX_NODISCARD + _GLIBCXX20_CONSTEXPR reference front() _GLIBCXX_NOEXCEPT { @@ -462,6 +530,7 @@ namespace __debug } _GLIBCXX_NODISCARD + _GLIBCXX20_CONSTEXPR const_reference front() const _GLIBCXX_NOEXCEPT { @@ -470,6 +539,7 @@ namespace __debug } _GLIBCXX_NODISCARD + _GLIBCXX20_CONSTEXPR reference back() _GLIBCXX_NOEXCEPT { @@ -478,6 +548,7 @@ namespace __debug } _GLIBCXX_NODISCARD + _GLIBCXX20_CONSTEXPR const_reference back() const _GLIBCXX_NOEXCEPT { @@ -490,9 +561,13 @@ namespace __debug using _Base::data; // 23.2.4.3 modifiers: + _GLIBCXX20_CONSTEXPR void push_back(const _Tp& __x) { + if (std::__is_constant_evaluated()) + return _Base::push_back(__x); + bool __realloc = this->_M_requires_reallocation(this->size() + 1); _Base::push_back(__x); if (__realloc) @@ -502,12 +577,14 @@ namespace __debug #if __cplusplus >= 201103L template<typename _Up = _Tp> + _GLIBCXX20_CONSTEXPR typename __gnu_cxx::__enable_if<!std::__are_same<_Up, bool>::__value, void>::__type push_back(_Tp&& __x) { emplace_back(std::move(__x)); } template<typename... _Args> + _GLIBCXX20_CONSTEXPR #if __cplusplus > 201402L reference #else @@ -515,6 +592,9 @@ namespace __debug #endif emplace_back(_Args&&... __args) { + if (std::__is_constant_evaluated()) + return _Base::emplace_back(std::forward<_Args>(__args)...); + bool __realloc = this->_M_requires_reallocation(this->size() + 1); _Base::emplace_back(std::forward<_Args>(__args)...); if (__realloc) @@ -526,19 +606,29 @@ namespace __debug } #endif + _GLIBCXX20_CONSTEXPR void pop_back() _GLIBCXX_NOEXCEPT { - __glibcxx_check_nonempty(); - this->_M_invalidate_if(_Equal(--_Base::end())); + if (!std::__is_constant_evaluated()) + { + __glibcxx_check_nonempty(); + this->_M_invalidate_if(_Equal(--_Base::end())); + } _Base::pop_back(); } #if __cplusplus >= 201103L template<typename... _Args> + _GLIBCXX20_CONSTEXPR iterator emplace(const_iterator __position, _Args&&... __args) { + if (std::__is_constant_evaluated()) + return iterator(_Base::emplace(__position.base(), + std::forward<_Args>(__args)...), + this); + __glibcxx_check_insert(__position); bool __realloc = this->_M_requires_reallocation(this->size() + 1); difference_type __offset = __position.base() - _Base::cbegin(); @@ -553,6 +643,7 @@ namespace __debug } #endif + _GLIBCXX20_CONSTEXPR iterator #if __cplusplus >= 201103L insert(const_iterator __position, const _Tp& __x) @@ -560,6 +651,9 @@ namespace __debug insert(iterator __position, const _Tp& __x) #endif { + if (std::__is_constant_evaluated()) + return iterator(_Base::insert(__position.base(), __x), this); + __glibcxx_check_insert(__position); bool __realloc = this->_M_requires_reallocation(this->size() + 1); difference_type __offset = __position.base() - _Base::begin(); @@ -574,20 +668,26 @@ namespace __debug #if __cplusplus >= 201103L template<typename _Up = _Tp> + _GLIBCXX20_CONSTEXPR typename __gnu_cxx::__enable_if<!std::__are_same<_Up, bool>::__value, iterator>::__type insert(const_iterator __position, _Tp&& __x) { return emplace(__position, std::move(__x)); } + _GLIBCXX20_CONSTEXPR iterator insert(const_iterator __position, initializer_list<value_type> __l) { return this->insert(__position, __l.begin(), __l.end()); } #endif #if __cplusplus >= 201103L + _GLIBCXX20_CONSTEXPR iterator insert(const_iterator __position, size_type __n, const _Tp& __x) { + if (std::__is_constant_evaluated()) + return iterator(_Base::insert(__position.base(), __n, __x), this); + __glibcxx_check_insert(__position); bool __realloc = this->_M_requires_reallocation(this->size() + __n); difference_type __offset = __position.base() - _Base::cbegin(); @@ -618,10 +718,16 @@ namespace __debug #if __cplusplus >= 201103L template<class _InputIterator, typename = std::_RequireInputIter<_InputIterator>> + _GLIBCXX20_CONSTEXPR iterator insert(const_iterator __position, _InputIterator __first, _InputIterator __last) { + if (std::__is_constant_evaluated()) + return iterator(_Base::insert(__position.base(), + __gnu_debug::__unsafe(__first), + __gnu_debug::__unsafe(__last)), this); + typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist; __glibcxx_check_insert_range(__position, __first, __last, __dist); @@ -673,6 +779,7 @@ namespace __debug } #endif + _GLIBCXX20_CONSTEXPR iterator #if __cplusplus >= 201103L erase(const_iterator __position) @@ -680,6 +787,9 @@ namespace __debug erase(iterator __position) #endif { + if (std::__is_constant_evaluated()) + return iterator(_Base::erase(__position.base()), this); + __glibcxx_check_erase(__position); difference_type __offset = __position.base() - _Base::begin(); _Base_iterator __res = _Base::erase(__position.base()); @@ -687,6 +797,7 @@ namespace __debug return iterator(__res, this); } + _GLIBCXX20_CONSTEXPR iterator #if __cplusplus >= 201103L erase(const_iterator __first, const_iterator __last) @@ -694,6 +805,9 @@ namespace __debug erase(iterator __first, iterator __last) #endif { + if (std::__is_constant_evaluated()) + return iterator(_Base::erase(__first.base(), __last.base()), this); + // _GLIBCXX_RESOLVE_LIB_DEFECTS // 151. can't currently clear() empty container __glibcxx_check_erase_range(__first, __last); @@ -714,25 +828,31 @@ namespace __debug #endif } + _GLIBCXX20_CONSTEXPR void swap(vector& __x) _GLIBCXX_NOEXCEPT_IF( noexcept(declval<_Base&>().swap(__x)) ) { - _Safe::_M_swap(__x); + if (!std::__is_constant_evaluated()) + _Safe::_M_swap(__x); _Base::swap(__x); std::swap(this->_M_guaranteed_capacity, __x._M_guaranteed_capacity); } + _GLIBCXX20_CONSTEXPR void clear() _GLIBCXX_NOEXCEPT { _Base::clear(); - this->_M_invalidate_all(); + if (!std::__is_constant_evaluated()) + this->_M_invalidate_all(); } + _GLIBCXX20_CONSTEXPR _Base& _M_base() _GLIBCXX_NOEXCEPT { return *this; } + _GLIBCXX20_CONSTEXPR const _Base& _M_base() const _GLIBCXX_NOEXCEPT { return *this; } @@ -746,6 +866,7 @@ namespace __debug }; template<typename _Tp, typename _Alloc> + _GLIBCXX20_CONSTEXPR inline bool operator==(const vector<_Tp, _Alloc>& __lhs, const vector<_Tp, _Alloc>& __rhs) @@ -789,6 +910,7 @@ namespace __debug #endif // three-way comparison template<typename _Tp, typename _Alloc> + _GLIBCXX20_CONSTEXPR inline void swap(vector<_Tp, _Alloc>& __lhs, vector<_Tp, _Alloc>& __rhs) _GLIBCXX_NOEXCEPT_IF(noexcept(__lhs.swap(__rhs))) diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/capacity/constexpr.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/capacity/constexpr.cc index d44e9d97b46..534128c487e 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/bool/capacity/constexpr.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/bool/capacity/constexpr.cc @@ -1,5 +1,4 @@ // { dg-do compile { target c++20 } } -// { dg-xfail-if "not supported" { debug_mode } } #include <vector> #include <testsuite_hooks.h> 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 66197e0aa29..e852c388903 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,7 +16,6 @@ // <http://www.gnu.org/licenses/>. // { dg-do compile { target c++20 } } -// { dg-xfail-if "not supported" { debug_mode } } #include <vector> #include <testsuite_hooks.h> diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/cons/constexpr.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/cons/constexpr.cc index 0e0c1e1c5ec..88d99fe682f 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/bool/cons/constexpr.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/bool/cons/constexpr.cc @@ -1,5 +1,4 @@ // { dg-do compile { target c++20 } } -// { dg-xfail-if "not supported" { debug_mode } } #include <vector> #include <testsuite_hooks.h> diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/element_access/1.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/element_access/1.cc index 2a430845058..e7d710829e1 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/bool/element_access/1.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/bool/element_access/1.cc @@ -1,5 +1,4 @@ // { dg-do compile { target c++23 } } -// { dg-xfail-if "not supported" { debug_mode } } #include <vector> #include <testsuite_hooks.h> 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 index 5b8ca94e78f..d6b657e0161 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/bool/element_access/constexpr.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/bool/element_access/constexpr.cc @@ -1,5 +1,4 @@ // { dg-do compile { target c++20 } } -// { dg-xfail-if "not supported" { debug_mode } } #include <vector> #include <testsuite_hooks.h> 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 index 3ad7dda88a9..31a6793f7ff 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/assign/constexpr.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/assign/constexpr.cc @@ -1,5 +1,4 @@ // { dg-do compile { target c++20 } } -// { dg-xfail-if "not supported" { debug_mode } } #include <vector> #include <testsuite_hooks.h> diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/constexpr.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/constexpr.cc index 22a4df5e370..0e37f9aa786 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/constexpr.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/constexpr.cc @@ -1,5 +1,4 @@ // { dg-do compile { target c++20 } } -// { dg-xfail-if "not supported" { debug_mode } } #include <vector> #include <testsuite_hooks.h> 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 index 624ff96a9e9..d2a0218a109 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/swap/constexpr.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/swap/constexpr.cc @@ -1,5 +1,4 @@ // { dg-do compile { target c++20 } } -// { dg-xfail-if "not supported" { debug_mode } } #include <vector> #include <utility> @@ -49,6 +48,7 @@ test_member_swap() static_assert(test_member_swap()); +#ifndef _GLIBCXX_DEBUG constexpr bool test_reference_swap() { @@ -63,3 +63,4 @@ test_reference_swap() } static_assert(test_reference_swap()); +#endif diff --git a/libstdc++-v3/testsuite/23_containers/vector/capacity/constexpr.cc b/libstdc++-v3/testsuite/23_containers/vector/capacity/constexpr.cc index 018a4792891..c331dbd5e57 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/capacity/constexpr.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/capacity/constexpr.cc @@ -1,5 +1,4 @@ // { dg-do compile { target c++20 } } -// { dg-xfail-if "not supported" { debug_mode } } #include <vector> #include <testsuite_hooks.h> 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 72c5c6cd7f9..63cb92c0edf 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/cmp_c++20.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/cmp_c++20.cc @@ -16,7 +16,6 @@ // <http://www.gnu.org/licenses/>. // { dg-do compile { target c++20 } } -// { dg-xfail-if "not supported" { debug_mode } } #include <vector> #include <testsuite_hooks.h> diff --git a/libstdc++-v3/testsuite/23_containers/vector/cons/constexpr.cc b/libstdc++-v3/testsuite/23_containers/vector/cons/constexpr.cc index 7bf86511240..fa78676b300 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/cons/constexpr.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/cons/constexpr.cc @@ -1,6 +1,5 @@ // { dg-do compile { target c++20 } } // { dg-add-options no_pch } -// { dg-xfail-if "not supported" { debug_mode } } #include <vector> diff --git a/libstdc++-v3/testsuite/23_containers/vector/data_access/constexpr.cc b/libstdc++-v3/testsuite/23_containers/vector/data_access/constexpr.cc index f5b601a44f4..142050e8f03 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/data_access/constexpr.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/data_access/constexpr.cc @@ -1,5 +1,4 @@ // { dg-do compile { target c++20 } } -// { dg-xfail-if "not supported" { debug_mode } } #include <vector> #include <testsuite_hooks.h> diff --git a/libstdc++-v3/testsuite/23_containers/vector/element_access/constexpr.cc b/libstdc++-v3/testsuite/23_containers/vector/element_access/constexpr.cc index 60c66dcc647..ee93d2fd95e 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/element_access/constexpr.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/element_access/constexpr.cc @@ -1,5 +1,4 @@ // { dg-do compile { target c++20 } } -// { dg-xfail-if "not supported" { debug_mode } } #include <vector> #include <testsuite_hooks.h> diff --git a/libstdc++-v3/testsuite/23_containers/vector/modifiers/assign/constexpr.cc b/libstdc++-v3/testsuite/23_containers/vector/modifiers/assign/constexpr.cc index cca20f4291c..41fc8d9696e 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/modifiers/assign/constexpr.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/modifiers/assign/constexpr.cc @@ -1,5 +1,4 @@ // { dg-do compile { target c++20 } } -// { dg-xfail-if "not supported" { debug_mode } } #include <vector> #include <testsuite_hooks.h> diff --git a/libstdc++-v3/testsuite/23_containers/vector/modifiers/constexpr.cc b/libstdc++-v3/testsuite/23_containers/vector/modifiers/constexpr.cc index 766e3a7690f..4aa1f1f67b7 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/modifiers/constexpr.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/modifiers/constexpr.cc @@ -1,5 +1,4 @@ // { dg-do compile { target c++20 } } -// { dg-xfail-if "not supported" { debug_mode } } #include <vector> #include <testsuite_hooks.h> diff --git a/libstdc++-v3/testsuite/23_containers/vector/modifiers/swap/constexpr.cc b/libstdc++-v3/testsuite/23_containers/vector/modifiers/swap/constexpr.cc index 45b3986beca..77d2a518d69 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/modifiers/swap/constexpr.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/modifiers/swap/constexpr.cc @@ -1,5 +1,4 @@ // { dg-do compile { target c++20 } } -// { dg-xfail-if "not supported" { debug_mode } } #include <vector> #include <utility>