From b03c70857f55a553b681c43850491fc45bad2f11 Mon Sep 17 00:00:00 2001 From: Michael Schellenberger Costa Date: Mon, 21 Dec 2020 13:37:57 +0100 Subject: [PATCH 01/50] Prepare the constexpr machinery needed for string and vector --- stl/inc/xmemory | 431 +++++++++++++++++++++++++++++------------------ stl/inc/xutility | 14 +- 2 files changed, 280 insertions(+), 165 deletions(-) diff --git a/stl/inc/xmemory b/stl/inc/xmemory index 38209d5c9cd..73ecb33edbb 100644 --- a/stl/inc/xmemory +++ b/stl/inc/xmemory @@ -27,7 +27,7 @@ _STD_BEGIN template struct _NODISCARD _Tidy_guard { // class with destructor that calls _Tidy _Ty* _Target; - ~_Tidy_guard() { + _CONSTEXPR20_DYNALLOC ~_Tidy_guard() { if (_Target) { _Target->_Tidy(); } @@ -38,7 +38,7 @@ struct _NODISCARD _Tidy_guard { // class with destructor that calls _Tidy template struct _NODISCARD _Tidy_deallocate_guard { // class with destructor that calls _Tidy_deallocate _Ty* _Target; - ~_Tidy_deallocate_guard() { + _CONSTEXPR20_DYNALLOC ~_Tidy_deallocate_guard() { if (_Target) { _Target->_Tidy_deallocate(); } @@ -265,10 +265,10 @@ _CONSTEXPR20_DYNALLOC void _Deallocate(void* _Ptr, size_t _Bytes) noexcept { // FUNCTION TEMPLATE _Global_new template -_Ty* _Global_new(_Types&&... _Args) { // acts as "new" while disallowing user overload selection +_CONSTEXPR20_DYNALLOC _Ty* _Global_new(_Types&&... _Args) { // acts as "new" while disallowing user overload selection struct _NODISCARD _Guard_type { void* _Result; - ~_Guard_type() { + _CONSTEXPR20_DYNALLOC ~_Guard_type() { if (_Result) { _Deallocate<_New_alignof<_Ty>>(_Result, sizeof(_Ty)); } @@ -286,12 +286,12 @@ using _Rebind_pointer_t = typename pointer_traits<_Ptr>::template rebind<_Ty>; // FUNCTION TEMPLATE _Refancy template , int> = 0> -_Pointer _Refancy(typename pointer_traits<_Pointer>::element_type* _Ptr) noexcept { +_CONSTEXPR20 _Pointer _Refancy(typename pointer_traits<_Pointer>::element_type* _Ptr) noexcept { return pointer_traits<_Pointer>::pointer_to(*_Ptr); } template , int> = 0> -_Pointer _Refancy(_Pointer _Ptr) noexcept { +_CONSTEXPR20 _Pointer _Refancy(_Pointer _Ptr) noexcept { return _Ptr; } @@ -837,7 +837,7 @@ public: template _CXX17_DEPRECATE_OLD_ALLOCATOR_MEMBERS void construct(_Objty* const _Ptr, _Types&&... _Args) { - ::new (const_cast(static_cast(_Ptr))) _Objty(_STD forward<_Types>(_Args)...); + ::new (_Voidify_iter(_Ptr)) _Objty(_STD forward<_Types>(_Args)...); } template @@ -897,7 +897,7 @@ using _Alloc_size_t = typename allocator_traits<_Alloc>::size_type; // FUNCTION TEMPLATE _Pocca template -void _Pocca(_Alloc& _Left, const _Alloc& _Right) noexcept { +_CONSTEXPR20 void _Pocca(_Alloc& _Left, const _Alloc& _Right) noexcept { if constexpr (allocator_traits<_Alloc>::propagate_on_container_copy_assignment::value) { _Left = _Right; } @@ -905,7 +905,7 @@ void _Pocca(_Alloc& _Left, const _Alloc& _Right) noexcept { // FUNCTION TEMPLATE _Pocma template -void _Pocma(_Alloc& _Left, _Alloc& _Right) noexcept { // (maybe) propagate on container move assignment +_CONSTEXPR20 void _Pocma(_Alloc& _Left, _Alloc& _Right) noexcept { // (maybe) propagate on container move assignment if constexpr (allocator_traits<_Alloc>::propagate_on_container_move_assignment::value) { _Left = _STD move(_Right); } @@ -913,7 +913,7 @@ void _Pocma(_Alloc& _Left, _Alloc& _Right) noexcept { // (maybe) propagate on co // FUNCTION TEMPLATE _Pocs template -void _Pocs(_Alloc& _Left, _Alloc& _Right) noexcept { +_CONSTEXPR20 void _Pocs(_Alloc& _Left, _Alloc& _Right) noexcept { if constexpr (allocator_traits<_Alloc>::propagate_on_container_swap::value) { _Swap_adl(_Left, _Right); } else { @@ -923,7 +923,8 @@ void _Pocs(_Alloc& _Left, _Alloc& _Right) noexcept { // FUNCTION TEMPLATE _Destroy_range WITH ALLOC template -void _Destroy_range(_Alloc_ptr_t<_Alloc> _First, const _Alloc_ptr_t<_Alloc> _Last, _Alloc& _Al) noexcept { +_CONSTEXPR20_DYNALLOC void _Destroy_range( + _Alloc_ptr_t<_Alloc> _First, const _Alloc_ptr_t<_Alloc> _Last, _Alloc& _Al) noexcept { // note that this is an optimization for debug mode codegen; in release mode the BE removes all of this using _Ty = typename _Alloc::value_type; if constexpr (!conjunction_v, _Uses_default_destroy<_Alloc, _Ty*>>) { @@ -963,7 +964,7 @@ _NODISCARD constexpr size_t _Convert_size(const size_t _Len) noexcept { // FUNCTION TEMPLATE _Deallocate_plain template -void _Deallocate_plain(_Alloc& _Al, typename _Alloc::value_type* const _Ptr) noexcept { +_CONSTEXPR20_DYNALLOC void _Deallocate_plain(_Alloc& _Al, typename _Alloc::value_type* const _Ptr) noexcept { // deallocate a plain pointer using an allocator using _Alloc_traits = allocator_traits<_Alloc>; if constexpr (is_same_v<_Alloc_ptr_t<_Alloc>, typename _Alloc::value_type*>) { @@ -976,7 +977,7 @@ void _Deallocate_plain(_Alloc& _Al, typename _Alloc::value_type* const _Ptr) noe // FUNCTION TEMPLATE _Delete_plain_internal template -void _Delete_plain_internal(_Alloc& _Al, typename _Alloc::value_type* const _Ptr) noexcept { +_CONSTEXPR20_DYNALLOC void _Delete_plain_internal(_Alloc& _Al, typename _Alloc::value_type* const _Ptr) noexcept { // destroy *_Ptr in place, then deallocate _Ptr using _Al; used for internal container types the user didn't name using _Ty = typename _Alloc::value_type; _Ptr->~_Ty(); @@ -992,16 +993,16 @@ struct _Alloc_construct_ptr { // pointer used to help construct 1 _Alloc::value_ explicit _Alloc_construct_ptr(_Alloc& _Al_) : _Al(_Al_), _Ptr(nullptr) {} - _NODISCARD pointer _Release() noexcept { // disengage *this and return contained pointer + _NODISCARD _CONSTEXPR20_DYNALLOC pointer _Release() noexcept { // disengage *this and return contained pointer return _STD exchange(_Ptr, nullptr); } - void _Allocate() { // disengage *this, then allocate a new memory block + _CONSTEXPR20_DYNALLOC void _Allocate() { // disengage *this, then allocate a new memory block _Ptr = nullptr; // if allocate throws, prevents double-free _Ptr = _Al.allocate(1); } - ~_Alloc_construct_ptr() { // if this instance is engaged, deallocate storage + _CONSTEXPR20_DYNALLOC ~_Alloc_construct_ptr() { // if this instance is engaged, deallocate storage if (_Ptr) { _Al.deallocate(_Ptr, 1); } @@ -1015,15 +1016,15 @@ struct _Alloc_construct_ptr { // pointer used to help construct 1 _Alloc::value_ struct _Fake_allocator {}; struct _Container_base0 { - void _Orphan_all() noexcept {} - void _Swap_proxy_and_iterators(_Container_base0&) noexcept {} - void _Alloc_proxy(const _Fake_allocator&) noexcept {} - void _Reload_proxy(const _Fake_allocator&, const _Fake_allocator&) noexcept {} + _CONSTEXPR20 void _Orphan_all() noexcept {} + _CONSTEXPR20 void _Swap_proxy_and_iterators(_Container_base0&) noexcept {} + _CONSTEXPR20 void _Alloc_proxy(const _Fake_allocator&) noexcept {} + _CONSTEXPR20 void _Reload_proxy(const _Fake_allocator&, const _Fake_allocator&) noexcept {} }; struct _Iterator_base0 { - void _Adopt(const void*) noexcept {} - const _Container_base0* _Getcont() const noexcept { + _CONSTEXPR20 void _Adopt(const void*) noexcept {} + _CONSTEXPR20 const _Container_base0* _Getcont() const noexcept { return nullptr; } @@ -1033,25 +1034,25 @@ struct _Iterator_base0 { // CLASS _Container_proxy struct _Container_base12; struct _Container_proxy { // store head of iterator chain and back pointer - _Container_proxy() noexcept : _Mycont(nullptr), _Myfirstiter(nullptr) {} - _Container_proxy(_Container_base12* _Mycont_) noexcept : _Mycont(_Mycont_), _Myfirstiter(nullptr) {} + _CONSTEXPR20 _Container_proxy() noexcept = default; + _CONSTEXPR20 _Container_proxy(_Container_base12* _Mycont_) noexcept : _Mycont(_Mycont_) {} const _Container_base12* _Mycont; - _Iterator_base12* _Myfirstiter; + mutable _Iterator_base12* _Myfirstiter; }; struct _Container_base12 { public: - _Container_base12() noexcept : _Myproxy(nullptr) {} + _CONSTEXPR20_DYNALLOC _Container_base12() noexcept = default; _Container_base12(const _Container_base12&) = delete; _Container_base12& operator=(const _Container_base12&) = delete; - void _Orphan_all() noexcept; - void _Swap_proxy_and_iterators(_Container_base12&) noexcept; + _CONSTEXPR20_DYNALLOC void _Orphan_all() noexcept; + _CONSTEXPR20_DYNALLOC void _Swap_proxy_and_iterators(_Container_base12&) noexcept; template - void _Alloc_proxy(_Alloc&& _Al) { + _CONSTEXPR20_DYNALLOC void _Alloc_proxy(_Alloc&& _Al) { _Container_proxy* const _New_proxy = _Unfancy(_Al.allocate(1)); _Construct_in_place(*_New_proxy, this); _Myproxy = _New_proxy; @@ -1059,7 +1060,7 @@ public: } template - void _Reload_proxy(_Alloc&& _Old_alloc, _Alloc&& _New_alloc) { + _CONSTEXPR20_DYNALLOC void _Reload_proxy(_Alloc&& _Old_alloc, _Alloc&& _New_alloc) { // pre: no iterators refer to the existing proxy _Container_proxy* const _New_proxy = _Unfancy(_New_alloc.allocate(1)); _Construct_in_place(*_New_proxy, this); @@ -1067,113 +1068,156 @@ public: _Delete_plain_internal(_Old_alloc, _STD exchange(_Myproxy, _New_proxy)); } - _Container_proxy* _Myproxy; + _Container_proxy* _Myproxy = nullptr; + +private: + _CONSTEXPR20_DYNALLOC void _Orphan_all_unlocked() noexcept; + inline void _Orphan_all_locked() noexcept; + _CONSTEXPR20_DYNALLOC void _Swap_proxy_and_iterators_unlocked(_Container_base12&) noexcept; + inline void _Swap_proxy_and_iterators_locked(_Container_base12&) noexcept; }; struct _Iterator_base12 { // store links to container proxy, next iterator - _Iterator_base12() noexcept : _Myproxy(nullptr), _Mynextiter(nullptr) {} // construct orphaned iterator +public: + _CONSTEXPR20_DYNALLOC _Iterator_base12() noexcept = default; // construct orphaned iterator - _Iterator_base12(const _Iterator_base12& _Right) noexcept : _Myproxy(nullptr), _Mynextiter(nullptr) { + _CONSTEXPR20_DYNALLOC _Iterator_base12(const _Iterator_base12& _Right) noexcept { *this = _Right; } - _Iterator_base12& operator=(const _Iterator_base12& _Right) noexcept { + _CONSTEXPR20_DYNALLOC _Iterator_base12& operator=(const _Iterator_base12& _Right) noexcept { if (_Myproxy != _Right._Myproxy) { if (_Right._Myproxy) { _Adopt(_Right._Myproxy->_Mycont); } else { // becoming invalid, disown current parent #if _ITERATOR_DEBUG_LEVEL == 2 - _Lockit _Lock(_LOCK_DEBUG); _Orphan_me(); #else // _ITERATOR_DEBUG_LEVEL == 2 _Myproxy = nullptr; #endif // _ITERATOR_DEBUG_LEVEL == 2 } } - return *this; } - ~_Iterator_base12() noexcept { #if _ITERATOR_DEBUG_LEVEL == 2 - _Lockit _Lock(_LOCK_DEBUG); + _CONSTEXPR20_DYNALLOC ~_Iterator_base12() noexcept { _Orphan_me(); -#endif // _ITERATOR_DEBUG_LEVEL == 2 } - void _Adopt(const _Container_base12* _Parent) noexcept { - if (_Parent) { - // have a parent, do adoption + _CONSTEXPR20_DYNALLOC void _Adopt(const _Container_base12* _Parent) noexcept { + if (_Parent) { // have a parent, do adoption _Container_proxy* _Parent_proxy = _Parent->_Myproxy; - -#if _ITERATOR_DEBUG_LEVEL == 2 if (_Myproxy != _Parent_proxy) { // change parentage - _Lockit _Lock(_LOCK_DEBUG); - _Orphan_me(); - _Mynextiter = _Parent_proxy->_Myfirstiter; - _Parent_proxy->_Myfirstiter = this; - _Myproxy = _Parent_proxy; +#ifdef __cpp_lib_is_constant_evaluated + if (_STD is_constant_evaluated()) { + _Adopt_unlocked(_Parent_proxy); + } else +#endif // __cpp_lib_is_constant_evaluated + { + _Adopt_locked(_Parent_proxy); + } } - -#else // _ITERATOR_DEBUG_LEVEL == 2 - _Myproxy = _Parent_proxy; -#endif // _ITERATOR_DEBUG_LEVEL == 2 - } else { - // no future parent, just disown current parent -#if _ITERATOR_DEBUG_LEVEL == 2 - _Lockit _Lock(_LOCK_DEBUG); + } else { // no future parent, just disown current parent _Orphan_me(); -#else // _ITERATOR_DEBUG_LEVEL == 2 - _Myproxy = nullptr; -#endif // _ITERATOR_DEBUG_LEVEL == 2 } } - const _Container_base12* _Getcont() const noexcept { - return _Myproxy ? _Myproxy->_Mycont : nullptr; - } - -#if _ITERATOR_DEBUG_LEVEL == 2 - void _Orphan_me() noexcept { + _CONSTEXPR20_DYNALLOC void _Orphan_me() noexcept { if (_Myproxy) { // adopted, remove self from list - _Iterator_base12** _Pnext = &_Myproxy->_Myfirstiter; - while (*_Pnext && *_Pnext != this) { - _Pnext = &(*_Pnext)->_Mynextiter; +#ifdef __cpp_lib_is_constant_evaluated + if (_STD is_constant_evaluated()) { + _Orphan_me_unlocked(); + } else +#endif // __cpp_lib_is_constant_evaluated + { + _Orphan_me_locked(); } + } + } - _STL_VERIFY(*_Pnext, "ITERATOR LIST CORRUPTED!"); - *_Pnext = _Mynextiter; +#else // ^^^ _ITERATOR_DEBUG_LEVEL == 2 ^^^ / vvv _ITERATOR_DEBUG_LEVEL != 2 vvv + _CONSTEXPR20_DYNALLOC void _Adopt(const _Container_base12* _Parent) noexcept { + if (_Parent) { // have a parent, do adoption + _Myproxy = _Parent->_Myproxy; + } else { // no future parent, just disown current parent _Myproxy = nullptr; } } -#endif // _ITERATOR_DEBUG_LEVEL == 2 +#endif // _ITERATOR_DEBUG_LEVEL != 2 + + _CONSTEXPR20_DYNALLOC const _Container_base12* _Getcont() const noexcept { + return _Myproxy ? _Myproxy->_Mycont : nullptr; + } static constexpr bool _Unwrap_when_unverified = _ITERATOR_DEBUG_LEVEL == 0; - _Container_proxy* _Myproxy; - _Iterator_base12* _Mynextiter; -}; + _Container_proxy* _Myproxy = nullptr; + _Iterator_base12* _Mynextiter = nullptr; -// MEMBER FUNCTIONS FOR _Container_base12 -inline void _Container_base12::_Orphan_all() noexcept { #if _ITERATOR_DEBUG_LEVEL == 2 - if (_Myproxy) { // proxy allocated, drain it +private: + _CONSTEXPR20_DYNALLOC void _Adopt_unlocked(_Container_proxy* _Parent_proxy) noexcept { + if (_Myproxy) { // adopted, remove self from list + _Orphan_me_unlocked(); + } + _Mynextiter = _Parent_proxy->_Myfirstiter; + _Parent_proxy->_Myfirstiter = this; + _Myproxy = _Parent_proxy; + } + + void _Adopt_locked(_Container_proxy* _Parent_proxy) noexcept { _Lockit _Lock(_LOCK_DEBUG); + _Adopt_unlocked(_Parent_proxy); + } - for (auto _Pnext = &_Myproxy->_Myfirstiter; *_Pnext; *_Pnext = (*_Pnext)->_Mynextiter) { - (*_Pnext)->_Myproxy = nullptr; + _CONSTEXPR20_DYNALLOC void _Orphan_me_unlocked() noexcept { + _Iterator_base12** _Pnext = &_Myproxy->_Myfirstiter; + while (*_Pnext && *_Pnext != this) { + _Pnext = &(*_Pnext)->_Mynextiter; } - _Myproxy->_Myfirstiter = nullptr; + _STL_VERIFY(*_Pnext, "ITERATOR LIST CORRUPTED!"); + *_Pnext = _Mynextiter; + _Myproxy = nullptr; + } + + void _Orphan_me_locked() noexcept { + _Lockit _Lock(_LOCK_DEBUG); + _Orphan_me_unlocked(); } #endif // _ITERATOR_DEBUG_LEVEL == 2 +}; + +// MEMBER FUNCTIONS FOR _Container_base12 +_CONSTEXPR20_DYNALLOC void _Container_base12::_Orphan_all_unlocked() noexcept { + for (auto _Pnext = &_Myproxy->_Myfirstiter; *_Pnext; *_Pnext = (*_Pnext)->_Mynextiter) { + (*_Pnext)->_Myproxy = nullptr; + } + _Myproxy->_Myfirstiter = nullptr; } -inline void _Container_base12::_Swap_proxy_and_iterators(_Container_base12& _Right) noexcept { -#if _ITERATOR_DEBUG_LEVEL == 2 +inline void _Container_base12::_Orphan_all_locked() noexcept { _Lockit _Lock(_LOCK_DEBUG); + _Orphan_all_unlocked(); +} + +_CONSTEXPR20_DYNALLOC void _Container_base12::_Orphan_all() noexcept { +#if _ITERATOR_DEBUG_LEVEL == 2 + if (_Myproxy) { // proxy allocated, drain it +#ifdef __cpp_lib_is_constant_evaluated + if (_STD is_constant_evaluated()) { + _Orphan_all_unlocked(); + } else +#endif // __cpp_lib_is_constant_evaluated + { + _Orphan_all_locked(); + } + } #endif // _ITERATOR_DEBUG_LEVEL == 2 +} +_CONSTEXPR20_DYNALLOC void _Container_base12::_Swap_proxy_and_iterators_unlocked(_Container_base12& _Right) noexcept { _Container_proxy* _Temp = _Myproxy; _Myproxy = _Right._Myproxy; _Right._Myproxy = _Temp; @@ -1187,6 +1231,26 @@ inline void _Container_base12::_Swap_proxy_and_iterators(_Container_base12& _Rig } } +inline void _Container_base12::_Swap_proxy_and_iterators_locked(_Container_base12& _Right) noexcept { + _Lockit _Lock(_LOCK_DEBUG); + _Swap_proxy_and_iterators_unlocked(_Right); +} + +_CONSTEXPR20_DYNALLOC void _Container_base12::_Swap_proxy_and_iterators(_Container_base12& _Right) noexcept { +#if _ITERATOR_DEBUG_LEVEL != 2 + _Swap_proxy_and_iterators_unlocked(_Right); +#else // ^^^ _ITERATOR_DEBUG_LEVEL != 2 ^^^ / vvv _ITERATOR_DEBUG_LEVEL == 2 vvv +#ifdef __cpp_lib_is_constant_evaluated + if (_STD is_constant_evaluated()) { + _Swap_proxy_and_iterators_unlocked(_Right); + } else +#endif // __cpp_lib_is_constant_evaluated + { + _Swap_proxy_and_iterators_locked(_Right); + } +#endif // _ITERATOR_DEBUG_LEVEL == 2 +} + #if _ITERATOR_DEBUG_LEVEL == 0 using _Container_base = _Container_base0; using _Iterator_base = _Iterator_base0; @@ -1203,23 +1267,23 @@ struct _Leave_proxy_unbound { struct _Fake_proxy_ptr_impl { // fake replacement for a container proxy smart pointer when no container proxy is in use _Fake_proxy_ptr_impl(const _Fake_proxy_ptr_impl&) = delete; _Fake_proxy_ptr_impl& operator=(const _Fake_proxy_ptr_impl&) = delete; - _Fake_proxy_ptr_impl(const _Fake_allocator&, _Leave_proxy_unbound) noexcept {} - _Fake_proxy_ptr_impl(const _Fake_allocator&, const _Container_base0&) noexcept {} + _CONSTEXPR20_DYNALLOC _Fake_proxy_ptr_impl(const _Fake_allocator&, _Leave_proxy_unbound) noexcept {} + _CONSTEXPR20_DYNALLOC _Fake_proxy_ptr_impl(const _Fake_allocator&, const _Container_base0&) noexcept {} - void _Bind(const _Fake_allocator&, _Container_base0*) noexcept {} - void _Release() noexcept {} + _CONSTEXPR20_DYNALLOC void _Bind(const _Fake_allocator&, _Container_base0*) noexcept {} + _CONSTEXPR20_DYNALLOC void _Release() noexcept {} }; struct _Basic_container_proxy_ptr12 { // smart pointer components for a _Container_proxy * that don't depend on the allocator _Container_proxy* _Ptr; - void _Release() noexcept { // disengage this _Basic_container_proxy_ptr12 + constexpr void _Release() noexcept { // disengage this _Basic_container_proxy_ptr12 _Ptr = nullptr; } protected: - _Basic_container_proxy_ptr12() = default; + _CONSTEXPR20_DYNALLOC _Basic_container_proxy_ptr12() = default; _Basic_container_proxy_ptr12(const _Basic_container_proxy_ptr12&) = delete; _Basic_container_proxy_ptr12(_Basic_container_proxy_ptr12&&) = delete; }; @@ -1229,26 +1293,27 @@ struct _Container_proxy_ptr12 : _Basic_container_proxy_ptr12 { // smart pointer components for a _Container_proxy * for an allocator family _Alloc& _Al; - _Container_proxy_ptr12(_Alloc& _Al_, _Leave_proxy_unbound) : _Al(_Al_) { // create a new unbound _Container_proxy + _CONSTEXPR20_DYNALLOC _Container_proxy_ptr12(_Alloc& _Al_, _Leave_proxy_unbound) : _Al(_Al_) { + // create a new unbound _Container_proxy _Ptr = _Unfancy(_Al_.allocate(1)); _Construct_in_place(*_Ptr); } - _Container_proxy_ptr12(_Alloc& _Al_, _Container_base12& _Mycont) - : _Al(_Al_) { // create a new _Container_proxy pointing at _Mycont + _CONSTEXPR20_DYNALLOC _Container_proxy_ptr12(_Alloc& _Al_, _Container_base12& _Mycont) : _Al(_Al_) { + // create a new _Container_proxy pointing at _Mycont _Ptr = _Unfancy(_Al_.allocate(1)); _Construct_in_place(*_Ptr, _STD addressof(_Mycont)); _Mycont._Myproxy = _Ptr; } - void _Bind(_Alloc& _Old_alloc, _Container_base12* _Mycont) noexcept { + _CONSTEXPR20_DYNALLOC void _Bind(_Alloc& _Old_alloc, _Container_base12* _Mycont) noexcept { // Attach the proxy stored in *this to _Mycont, and destroy _Mycont's existing proxy // with _Old_alloc. Requires that no iterators are alive referring to _Mycont. _Ptr->_Mycont = _Mycont; _Delete_plain_internal(_Old_alloc, _STD exchange(_Mycont->_Myproxy, _STD exchange(_Ptr, nullptr))); } - ~_Container_proxy_ptr12() { + _CONSTEXPR20_DYNALLOC ~_Container_proxy_ptr12() { if (_Ptr) { _Delete_plain_internal(_Al, _Ptr); } @@ -1381,18 +1446,18 @@ struct _NODISCARD _Uninitialized_backout { _Uninitialized_backout(const _Uninitialized_backout&) = delete; _Uninitialized_backout& operator=(const _Uninitialized_backout&) = delete; - ~_Uninitialized_backout() { + _CONSTEXPR20_DYNALLOC ~_Uninitialized_backout() { _Destroy_range(_First, _Last); } template - void _Emplace_back(_Types&&... _Vals) { + _CONSTEXPR20_DYNALLOC void _Emplace_back(_Types&&... _Vals) { // construct a new element at *_Last and increment _Construct_in_place(*_Last, _STD forward<_Types>(_Vals)...); ++_Last; } - _NoThrowFwdIt _Release() { // suppress any exception handling backout and return _Last + constexpr _NoThrowFwdIt _Release() { // suppress any exception handling backout and return _Last _First = _Last; return _Last; } @@ -1425,18 +1490,23 @@ namespace ranges { // FUNCTION TEMPLATE _Uninitialized_move_unchecked template -_NoThrowFwdIt _Uninitialized_move_unchecked(_InIt _First, const _InIt _Last, _NoThrowFwdIt _Dest) { +_CONSTEXPR20_DYNALLOC _NoThrowFwdIt _Uninitialized_move_unchecked( + _InIt _First, const _InIt _Last, _NoThrowFwdIt _Dest) { // move [_First, _Last) to raw [_Dest, ...) if constexpr (_Ptr_move_cat<_InIt, _NoThrowFwdIt>::_Really_trivial) { - return _Copy_memmove(_First, _Last, _Dest); - } else { - _Uninitialized_backout<_NoThrowFwdIt> _Backout{_Dest}; - for (; _First != _Last; ++_First) { - _Backout._Emplace_back(_STD move(*_First)); +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + return _Copy_memmove(_First, _Last, _Dest); } - - return _Backout._Release(); } + _Uninitialized_backout<_NoThrowFwdIt> _Backout{_Dest}; + for (; _First != _Last; ++_First) { + _Backout._Emplace_back(_STD move(*_First)); + } + + return _Backout._Release(); } // STRUCT TEMPLATE _Uninitialized_backout_al @@ -1446,22 +1516,23 @@ class _NODISCARD _Uninitialized_backout_al { using pointer = _Alloc_ptr_t<_Alloc>; public: - _Uninitialized_backout_al(pointer _Dest, _Alloc& _Al_) : _First(_Dest), _Last(_Dest), _Al(_Al_) {} + _CONSTEXPR20_DYNALLOC _Uninitialized_backout_al(pointer _Dest, _Alloc& _Al_) + : _First(_Dest), _Last(_Dest), _Al(_Al_) {} _Uninitialized_backout_al(const _Uninitialized_backout_al&) = delete; _Uninitialized_backout_al& operator=(const _Uninitialized_backout_al&) = delete; - ~_Uninitialized_backout_al() { + _CONSTEXPR20_DYNALLOC ~_Uninitialized_backout_al() { _Destroy_range(_First, _Last, _Al); } template - void _Emplace_back(_Types&&... _Vals) { // construct a new element at *_Last and increment + _CONSTEXPR20_DYNALLOC void _Emplace_back(_Types&&... _Vals) { // construct a new element at *_Last and increment allocator_traits<_Alloc>::construct(_Al, _Unfancy(_Last), _STD forward<_Types>(_Vals)...); ++_Last; } - pointer _Release() { // suppress any exception handling backout and return _Last + _CONSTEXPR20_DYNALLOC pointer _Release() { // suppress any exception handling backout and return _Last _First = _Last; return _Last; } @@ -1474,7 +1545,7 @@ private: // FUNCTION TEMPLATE _Uninitialized_copy WITH ALLOCATOR template -_Alloc_ptr_t<_Alloc> _Uninitialized_copy( +_CONSTEXPR20_DYNALLOC _Alloc_ptr_t<_Alloc> _Uninitialized_copy( const _InIt _First, const _InIt _Last, _Alloc_ptr_t<_Alloc> _Dest, _Alloc& _Al) { // copy [_First, _Last) to raw _Dest, using _Al // note: only called internally from elsewhere in the STL @@ -1485,21 +1556,48 @@ _Alloc_ptr_t<_Alloc> _Uninitialized_copy( if constexpr (conjunction_v::_Really_trivial>, _Uses_default_construct<_Alloc, _Ptrval, decltype(*_UFirst)>>) { - _Copy_memmove(_UFirst, _ULast, _Unfancy(_Dest)); - _Dest += _ULast - _UFirst; - } else { - _Uninitialized_backout_al<_Alloc> _Backout{_Dest, _Al}; - for (; _UFirst != _ULast; ++_UFirst) { - _Backout._Emplace_back(*_UFirst); +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + _Copy_memmove(_UFirst, _ULast, _Unfancy(_Dest)); + _Dest += _ULast - _UFirst; + return _Dest; } - - _Dest = _Backout._Release(); + } + _Uninitialized_backout_al<_Alloc> _Backout{_Dest, _Al}; + for (; _UFirst != _ULast; ++_UFirst) { + _Backout._Emplace_back(*_UFirst); } + _Dest = _Backout._Release(); + return _Dest; } // FUNCTION TEMPLATE uninitialized_copy +template +_CONSTEXPR20_DYNALLOC _NoThrowFwdIt _Uninitialized_copy_unchecked( + _InIt _First, const _InIt _Last, _NoThrowFwdIt _Dest) { + // copy [_First, _Last) to raw [_Dest, ...) + if constexpr (_Ptr_move_cat<_InIt, _NoThrowFwdIt>::_Really_trivial) { +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + return _Copy_memmove(_First, _Last, _Dest); + } + } + _Uninitialized_backout<_NoThrowFwdIt> _Backout{_Dest}; + for (; _First != _Last; ++_First) { + _Backout._Emplace_back(*_First); + } + + _Dest = _Backout._Release(); + + return _Dest; +} + template _NoThrowFwdIt uninitialized_copy(const _InIt _First, const _InIt _Last, _NoThrowFwdIt _Dest) { // copy [_First, _Last) to raw [_Dest, ...) @@ -1507,24 +1605,13 @@ _NoThrowFwdIt uninitialized_copy(const _InIt _First, const _InIt _Last, _NoThrow auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); auto _UDest = _Get_unwrapped_n(_Dest, _Idl_distance<_InIt>(_UFirst, _ULast)); - if constexpr (_Ptr_copy_cat::_Really_trivial) { - _UDest = _Copy_memmove(_UFirst, _ULast, _UDest); - } else { - _Uninitialized_backout _Backout{_UDest}; - for (; _UFirst != _ULast; ++_UFirst) { - _Backout._Emplace_back(*_UFirst); - } - - _UDest = _Backout._Release(); - } - - _Seek_wrapped(_Dest, _UDest); + _Seek_wrapped(_Dest, _Uninitialized_copy_unchecked(_UFirst, _ULast, _UDest)); return _Dest; } // FUNCTION TEMPLATE _Uninitialized_move WITH ALLOCATOR template -_Alloc_ptr_t<_Alloc> _Uninitialized_move( +_CONSTEXPR20_DYNALLOC _Alloc_ptr_t<_Alloc> _Uninitialized_move( const _InIt _First, const _InIt _Last, _Alloc_ptr_t<_Alloc> _Dest, _Alloc& _Al) { // move [_First, _Last) to raw _Dest, using _Al // note: only called internally from elsewhere in the STL @@ -1533,41 +1620,54 @@ _Alloc_ptr_t<_Alloc> _Uninitialized_move( const auto _ULast = _Get_unwrapped(_Last); if constexpr (conjunction_v::_Really_trivial>, _Uses_default_construct<_Alloc, _Ptrval, decltype(_STD move(*_UFirst))>>) { - _Copy_memmove(_UFirst, _ULast, _Unfancy(_Dest)); - return _Dest + (_ULast - _UFirst); - } else { - _Uninitialized_backout_al<_Alloc> _Backout{_Dest, _Al}; - for (; _UFirst != _ULast; ++_UFirst) { - _Backout._Emplace_back(_STD move(*_UFirst)); +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + _Copy_memmove(_UFirst, _ULast, _Unfancy(_Dest)); + return _Dest + (_ULast - _UFirst); } - - return _Backout._Release(); } + _Uninitialized_backout_al<_Alloc> _Backout{_Dest, _Al}; + for (; _UFirst != _ULast; ++_UFirst) { + _Backout._Emplace_back(_STD move(*_UFirst)); + } + + return _Backout._Release(); } // FUNCTION TEMPLATE _Uninitialized_fill_n WITH ALLOCATOR template -_Alloc_ptr_t<_Alloc> _Uninitialized_fill_n( +_CONSTEXPR20_DYNALLOC _Alloc_ptr_t<_Alloc> _Uninitialized_fill_n( _Alloc_ptr_t<_Alloc> _First, _Alloc_size_t<_Alloc> _Count, const typename _Alloc::value_type& _Val, _Alloc& _Al) { // copy _Count copies of _Val to raw _First, using _Al using _Ty = typename _Alloc::value_type; if constexpr (_Fill_memset_is_safe<_Ty*, _Ty> && _Uses_default_construct<_Alloc, _Ty*, _Ty>::value) { - _Fill_memset(_Unfancy(_First), _Val, static_cast(_Count)); - return _First + _Count; - } else { - if constexpr (_Fill_zero_memset_is_safe<_Ty*, _Ty> && _Uses_default_construct<_Alloc, _Ty*, _Ty>::value) { +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + _Fill_memset(_Unfancy(_First), _Val, static_cast(_Count)); + return _First + _Count; + } + } else if constexpr (_Fill_zero_memset_is_safe<_Ty*, _Ty> && _Uses_default_construct<_Alloc, _Ty*, _Ty>::value) { +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { if (_Is_all_bits_zero(_Val)) { _Fill_zero_memset(_Unfancy(_First), static_cast(_Count)); return _First + _Count; } } - _Uninitialized_backout_al<_Alloc> _Backout{_First, _Al}; - for (; 0 < _Count; --_Count) { - _Backout._Emplace_back(_Val); - } + } + _Uninitialized_backout_al<_Alloc> _Backout{_First, _Al}; - return _Backout._Release(); + for (; 0 < _Count; --_Count) { + _Backout._Emplace_back(_Val); } + + return _Backout._Release(); } // FUNCTION TEMPLATE uninitialized_fill @@ -1610,22 +1710,26 @@ _Ptr _Zero_range(const _Ptr _First, const _Ptr _Last) { // fill [_First, _Last) } template -_Alloc_ptr_t<_Alloc> _Uninitialized_value_construct_n( +_CONSTEXPR20_DYNALLOC _Alloc_ptr_t<_Alloc> _Uninitialized_value_construct_n( _Alloc_ptr_t<_Alloc> _First, _Alloc_size_t<_Alloc> _Count, _Alloc& _Al) { // value-initialize _Count objects to raw _First, using _Al using _Ptrty = typename _Alloc::value_type*; if constexpr (_Use_memset_value_construct_v<_Ptrty> && _Uses_default_construct<_Alloc, _Ptrty>::value) { - auto _PFirst = _Unfancy(_First); - _Zero_range(_PFirst, _PFirst + _Count); - return _First + _Count; - } else { - _Uninitialized_backout_al<_Alloc> _Backout{_First, _Al}; - for (; 0 < _Count; --_Count) { - _Backout._Emplace_back(); +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + auto _PFirst = _Unfancy(_First); + _Zero_range(_PFirst, _PFirst + _Count); + return _First + _Count; } - - return _Backout._Release(); } + _Uninitialized_backout_al<_Alloc> _Backout{_First, _Al}; + for (; 0 < _Count; --_Count) { + _Backout._Emplace_back(); + } + + return _Backout._Release(); } template @@ -1788,7 +1892,8 @@ _NODISCARD _CONSTEXPR20 _FwdIt remove_if(_FwdIt _First, const _FwdIt _Last, _Pr // FUNCTION TEMPLATE _Erase_remove template -typename _Container::size_type _Erase_remove(_Container& _Cont, const _Uty& _Val) { // erase each element matching _Val +_CONSTEXPR20_DYNALLOC typename _Container::size_type _Erase_remove(_Container& _Cont, const _Uty& _Val) { + // erase each element matching _Val auto _First = _Cont.begin(); const auto _Last = _Cont.end(); const auto _Old_size = _Cont.size(); @@ -1799,7 +1904,8 @@ typename _Container::size_type _Erase_remove(_Container& _Cont, const _Uty& _Val // FUNCTION TEMPLATE _Erase_remove_if template -typename _Container::size_type _Erase_remove_if(_Container& _Cont, _Pr _Pred) { // erase each element satisfying _Pred +_CONSTEXPR20_DYNALLOC typename _Container::size_type _Erase_remove_if(_Container& _Cont, _Pr _Pred) { + // erase each element satisfying _Pred auto _First = _Cont.begin(); const auto _Last = _Cont.end(); const auto _Old_size = _Cont.size(); @@ -1810,7 +1916,8 @@ typename _Container::size_type _Erase_remove_if(_Container& _Cont, _Pr _Pred) { // FUNCTION TEMPLATE _Erase_nodes_if template -typename _Container::size_type _Erase_nodes_if(_Container& _Cont, _Pr _Pred) { // erase each element satisfying _Pred +typename _Container::size_type _Erase_nodes_if(_Container& _Cont, _Pr _Pred) { + // erase each element satisfying _Pred auto _First = _Cont.begin(); const auto _Last = _Cont.end(); const auto _Old_size = _Cont.size(); diff --git a/stl/inc/xutility b/stl/inc/xutility index 653646d5425..67f0e54f1b6 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -141,13 +141,21 @@ _CONSTEXPR20_DYNALLOC auto construct_at(_Ty* const _Location, _Types&&... _Args) // FUNCTION TEMPLATE _Construct_in_place template -void _Construct_in_place(_Ty& _Obj, _Types&&... _Args) noexcept(is_nothrow_constructible_v<_Ty, _Types...>) { - ::new (_Voidify_iter(_STD addressof(_Obj))) _Ty(_STD forward<_Types>(_Args)...); +_CONSTEXPR20_DYNALLOC void _Construct_in_place(_Ty& _Obj, _Types&&... _Args) noexcept( + is_nothrow_constructible_v<_Ty, _Types...>) { +#ifdef __cpp_lib_is_constant_evaluated + if (_STD is_constant_evaluated()) { + _STD construct_at(_STD addressof(_Obj), _STD forward<_Types>(_Args)...); + } else +#endif // __cpp_lib_is_constant_evaluated + { + ::new (_Voidify_iter(_STD addressof(_Obj))) _Ty(_STD forward<_Types>(_Args)...); + } } // FUNCTION TEMPLATE _Default_construct_in_place template -void _Default_construct_in_place(_Ty& _Obj) noexcept(is_nothrow_default_constructible_v<_Ty>) { +_CONSTEXPR20_DYNALLOC void _Default_construct_in_place(_Ty& _Obj) noexcept(is_nothrow_default_constructible_v<_Ty>) { ::new (_Voidify_iter(_STD addressof(_Obj))) _Ty; } From 0d8082aacd3bd713238f5181ef643c589628f885 Mon Sep 17 00:00:00 2001 From: Michael Schellenberger Costa Date: Mon, 11 Jan 2021 13:19:59 +0100 Subject: [PATCH 02/50] Properly initialize --- stl/inc/xmemory | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/xmemory b/stl/inc/xmemory index 73ecb33edbb..745907c3651 100644 --- a/stl/inc/xmemory +++ b/stl/inc/xmemory @@ -1037,8 +1037,8 @@ struct _Container_proxy { // store head of iterator chain and back pointer _CONSTEXPR20 _Container_proxy() noexcept = default; _CONSTEXPR20 _Container_proxy(_Container_base12* _Mycont_) noexcept : _Mycont(_Mycont_) {} - const _Container_base12* _Mycont; - mutable _Iterator_base12* _Myfirstiter; + const _Container_base12* _Mycont = nullptr; + mutable _Iterator_base12* _Myfirstiter = nullptr; }; struct _Container_base12 { From 0ca2b483658015ab23a2d007f63dac3e199730af Mon Sep 17 00:00:00 2001 From: Michael Schellenberger Costa Date: Mon, 18 Jan 2021 13:09:45 +0100 Subject: [PATCH 03/50] Use _CONSTEXPR20_CONTAINER --- stl/inc/xmemory | 76 ++++++++++++++++++++++---------------------- stl/inc/yvals_core.h | 7 ++++ 2 files changed, 45 insertions(+), 38 deletions(-) diff --git a/stl/inc/xmemory b/stl/inc/xmemory index 745907c3651..3497438a30a 100644 --- a/stl/inc/xmemory +++ b/stl/inc/xmemory @@ -1016,15 +1016,15 @@ struct _Alloc_construct_ptr { // pointer used to help construct 1 _Alloc::value_ struct _Fake_allocator {}; struct _Container_base0 { - _CONSTEXPR20 void _Orphan_all() noexcept {} - _CONSTEXPR20 void _Swap_proxy_and_iterators(_Container_base0&) noexcept {} - _CONSTEXPR20 void _Alloc_proxy(const _Fake_allocator&) noexcept {} - _CONSTEXPR20 void _Reload_proxy(const _Fake_allocator&, const _Fake_allocator&) noexcept {} + _CONSTEXPR20_CONTAINER void _Orphan_all() noexcept {} + _CONSTEXPR20_CONTAINER void _Swap_proxy_and_iterators(_Container_base0&) noexcept {} + _CONSTEXPR20_CONTAINER void _Alloc_proxy(const _Fake_allocator&) noexcept {} + _CONSTEXPR20_CONTAINER void _Reload_proxy(const _Fake_allocator&, const _Fake_allocator&) noexcept {} }; struct _Iterator_base0 { - _CONSTEXPR20 void _Adopt(const void*) noexcept {} - _CONSTEXPR20 const _Container_base0* _Getcont() const noexcept { + _CONSTEXPR20_CONTAINER void _Adopt(const void*) noexcept {} + _CONSTEXPR20_CONTAINER const _Container_base0* _Getcont() const noexcept { return nullptr; } @@ -1034,8 +1034,8 @@ struct _Iterator_base0 { // CLASS _Container_proxy struct _Container_base12; struct _Container_proxy { // store head of iterator chain and back pointer - _CONSTEXPR20 _Container_proxy() noexcept = default; - _CONSTEXPR20 _Container_proxy(_Container_base12* _Mycont_) noexcept : _Mycont(_Mycont_) {} + _CONSTEXPR20_CONTAINER _Container_proxy() noexcept = default; + _CONSTEXPR20_CONTAINER _Container_proxy(_Container_base12* _Mycont_) noexcept : _Mycont(_Mycont_) {} const _Container_base12* _Mycont = nullptr; mutable _Iterator_base12* _Myfirstiter = nullptr; @@ -1043,16 +1043,16 @@ struct _Container_proxy { // store head of iterator chain and back pointer struct _Container_base12 { public: - _CONSTEXPR20_DYNALLOC _Container_base12() noexcept = default; + _CONSTEXPR20_CONTAINER _Container_base12() noexcept = default; _Container_base12(const _Container_base12&) = delete; _Container_base12& operator=(const _Container_base12&) = delete; - _CONSTEXPR20_DYNALLOC void _Orphan_all() noexcept; - _CONSTEXPR20_DYNALLOC void _Swap_proxy_and_iterators(_Container_base12&) noexcept; + _CONSTEXPR20_CONTAINER void _Orphan_all() noexcept; + _CONSTEXPR20_CONTAINER void _Swap_proxy_and_iterators(_Container_base12&) noexcept; template - _CONSTEXPR20_DYNALLOC void _Alloc_proxy(_Alloc&& _Al) { + _CONSTEXPR20_CONTAINER void _Alloc_proxy(_Alloc&& _Al) { _Container_proxy* const _New_proxy = _Unfancy(_Al.allocate(1)); _Construct_in_place(*_New_proxy, this); _Myproxy = _New_proxy; @@ -1060,7 +1060,7 @@ public: } template - _CONSTEXPR20_DYNALLOC void _Reload_proxy(_Alloc&& _Old_alloc, _Alloc&& _New_alloc) { + _CONSTEXPR20_CONTAINER void _Reload_proxy(_Alloc&& _Old_alloc, _Alloc&& _New_alloc) { // pre: no iterators refer to the existing proxy _Container_proxy* const _New_proxy = _Unfancy(_New_alloc.allocate(1)); _Construct_in_place(*_New_proxy, this); @@ -1071,21 +1071,21 @@ public: _Container_proxy* _Myproxy = nullptr; private: - _CONSTEXPR20_DYNALLOC void _Orphan_all_unlocked() noexcept; + _CONSTEXPR20_CONTAINER void _Orphan_all_unlocked() noexcept; inline void _Orphan_all_locked() noexcept; - _CONSTEXPR20_DYNALLOC void _Swap_proxy_and_iterators_unlocked(_Container_base12&) noexcept; + _CONSTEXPR20_CONTAINER void _Swap_proxy_and_iterators_unlocked(_Container_base12&) noexcept; inline void _Swap_proxy_and_iterators_locked(_Container_base12&) noexcept; }; struct _Iterator_base12 { // store links to container proxy, next iterator public: - _CONSTEXPR20_DYNALLOC _Iterator_base12() noexcept = default; // construct orphaned iterator + _CONSTEXPR20_CONTAINER _Iterator_base12() noexcept = default; // construct orphaned iterator - _CONSTEXPR20_DYNALLOC _Iterator_base12(const _Iterator_base12& _Right) noexcept { + _CONSTEXPR20_CONTAINER _Iterator_base12(const _Iterator_base12& _Right) noexcept { *this = _Right; } - _CONSTEXPR20_DYNALLOC _Iterator_base12& operator=(const _Iterator_base12& _Right) noexcept { + _CONSTEXPR20_CONTAINER _Iterator_base12& operator=(const _Iterator_base12& _Right) noexcept { if (_Myproxy != _Right._Myproxy) { if (_Right._Myproxy) { _Adopt(_Right._Myproxy->_Mycont); @@ -1101,11 +1101,11 @@ public: } #if _ITERATOR_DEBUG_LEVEL == 2 - _CONSTEXPR20_DYNALLOC ~_Iterator_base12() noexcept { + _CONSTEXPR20_CONTAINER ~_Iterator_base12() noexcept { _Orphan_me(); } - _CONSTEXPR20_DYNALLOC void _Adopt(const _Container_base12* _Parent) noexcept { + _CONSTEXPR20_CONTAINER void _Adopt(const _Container_base12* _Parent) noexcept { if (_Parent) { // have a parent, do adoption _Container_proxy* _Parent_proxy = _Parent->_Myproxy; if (_Myproxy != _Parent_proxy) { // change parentage @@ -1123,7 +1123,7 @@ public: } } - _CONSTEXPR20_DYNALLOC void _Orphan_me() noexcept { + _CONSTEXPR20_CONTAINER void _Orphan_me() noexcept { if (_Myproxy) { // adopted, remove self from list #ifdef __cpp_lib_is_constant_evaluated if (_STD is_constant_evaluated()) { @@ -1137,7 +1137,7 @@ public: } #else // ^^^ _ITERATOR_DEBUG_LEVEL == 2 ^^^ / vvv _ITERATOR_DEBUG_LEVEL != 2 vvv - _CONSTEXPR20_DYNALLOC void _Adopt(const _Container_base12* _Parent) noexcept { + _CONSTEXPR20_CONTAINER void _Adopt(const _Container_base12* _Parent) noexcept { if (_Parent) { // have a parent, do adoption _Myproxy = _Parent->_Myproxy; } else { // no future parent, just disown current parent @@ -1146,7 +1146,7 @@ public: } #endif // _ITERATOR_DEBUG_LEVEL != 2 - _CONSTEXPR20_DYNALLOC const _Container_base12* _Getcont() const noexcept { + _CONSTEXPR20_CONTAINER const _Container_base12* _Getcont() const noexcept { return _Myproxy ? _Myproxy->_Mycont : nullptr; } @@ -1157,7 +1157,7 @@ public: #if _ITERATOR_DEBUG_LEVEL == 2 private: - _CONSTEXPR20_DYNALLOC void _Adopt_unlocked(_Container_proxy* _Parent_proxy) noexcept { + _CONSTEXPR20_CONTAINER void _Adopt_unlocked(_Container_proxy* _Parent_proxy) noexcept { if (_Myproxy) { // adopted, remove self from list _Orphan_me_unlocked(); } @@ -1171,7 +1171,7 @@ private: _Adopt_unlocked(_Parent_proxy); } - _CONSTEXPR20_DYNALLOC void _Orphan_me_unlocked() noexcept { + _CONSTEXPR20_CONTAINER void _Orphan_me_unlocked() noexcept { _Iterator_base12** _Pnext = &_Myproxy->_Myfirstiter; while (*_Pnext && *_Pnext != this) { _Pnext = &(*_Pnext)->_Mynextiter; @@ -1190,7 +1190,7 @@ private: }; // MEMBER FUNCTIONS FOR _Container_base12 -_CONSTEXPR20_DYNALLOC void _Container_base12::_Orphan_all_unlocked() noexcept { +_CONSTEXPR20_CONTAINER void _Container_base12::_Orphan_all_unlocked() noexcept { for (auto _Pnext = &_Myproxy->_Myfirstiter; *_Pnext; *_Pnext = (*_Pnext)->_Mynextiter) { (*_Pnext)->_Myproxy = nullptr; } @@ -1202,7 +1202,7 @@ inline void _Container_base12::_Orphan_all_locked() noexcept { _Orphan_all_unlocked(); } -_CONSTEXPR20_DYNALLOC void _Container_base12::_Orphan_all() noexcept { +_CONSTEXPR20_CONTAINER void _Container_base12::_Orphan_all() noexcept { #if _ITERATOR_DEBUG_LEVEL == 2 if (_Myproxy) { // proxy allocated, drain it #ifdef __cpp_lib_is_constant_evaluated @@ -1217,7 +1217,7 @@ _CONSTEXPR20_DYNALLOC void _Container_base12::_Orphan_all() noexcept { #endif // _ITERATOR_DEBUG_LEVEL == 2 } -_CONSTEXPR20_DYNALLOC void _Container_base12::_Swap_proxy_and_iterators_unlocked(_Container_base12& _Right) noexcept { +_CONSTEXPR20_CONTAINER void _Container_base12::_Swap_proxy_and_iterators_unlocked(_Container_base12& _Right) noexcept { _Container_proxy* _Temp = _Myproxy; _Myproxy = _Right._Myproxy; _Right._Myproxy = _Temp; @@ -1236,7 +1236,7 @@ inline void _Container_base12::_Swap_proxy_and_iterators_locked(_Container_base1 _Swap_proxy_and_iterators_unlocked(_Right); } -_CONSTEXPR20_DYNALLOC void _Container_base12::_Swap_proxy_and_iterators(_Container_base12& _Right) noexcept { +_CONSTEXPR20_CONTAINER void _Container_base12::_Swap_proxy_and_iterators(_Container_base12& _Right) noexcept { #if _ITERATOR_DEBUG_LEVEL != 2 _Swap_proxy_and_iterators_unlocked(_Right); #else // ^^^ _ITERATOR_DEBUG_LEVEL != 2 ^^^ / vvv _ITERATOR_DEBUG_LEVEL == 2 vvv @@ -1267,11 +1267,11 @@ struct _Leave_proxy_unbound { struct _Fake_proxy_ptr_impl { // fake replacement for a container proxy smart pointer when no container proxy is in use _Fake_proxy_ptr_impl(const _Fake_proxy_ptr_impl&) = delete; _Fake_proxy_ptr_impl& operator=(const _Fake_proxy_ptr_impl&) = delete; - _CONSTEXPR20_DYNALLOC _Fake_proxy_ptr_impl(const _Fake_allocator&, _Leave_proxy_unbound) noexcept {} - _CONSTEXPR20_DYNALLOC _Fake_proxy_ptr_impl(const _Fake_allocator&, const _Container_base0&) noexcept {} + _CONSTEXPR20_CONTAINER _Fake_proxy_ptr_impl(const _Fake_allocator&, _Leave_proxy_unbound) noexcept {} + _CONSTEXPR20_CONTAINER _Fake_proxy_ptr_impl(const _Fake_allocator&, const _Container_base0&) noexcept {} - _CONSTEXPR20_DYNALLOC void _Bind(const _Fake_allocator&, _Container_base0*) noexcept {} - _CONSTEXPR20_DYNALLOC void _Release() noexcept {} + _CONSTEXPR20_CONTAINER void _Bind(const _Fake_allocator&, _Container_base0*) noexcept {} + _CONSTEXPR20_CONTAINER void _Release() noexcept {} }; struct _Basic_container_proxy_ptr12 { @@ -1283,7 +1283,7 @@ struct _Basic_container_proxy_ptr12 { } protected: - _CONSTEXPR20_DYNALLOC _Basic_container_proxy_ptr12() = default; + _CONSTEXPR20_CONTAINER _Basic_container_proxy_ptr12() = default; _Basic_container_proxy_ptr12(const _Basic_container_proxy_ptr12&) = delete; _Basic_container_proxy_ptr12(_Basic_container_proxy_ptr12&&) = delete; }; @@ -1293,27 +1293,27 @@ struct _Container_proxy_ptr12 : _Basic_container_proxy_ptr12 { // smart pointer components for a _Container_proxy * for an allocator family _Alloc& _Al; - _CONSTEXPR20_DYNALLOC _Container_proxy_ptr12(_Alloc& _Al_, _Leave_proxy_unbound) : _Al(_Al_) { + _CONSTEXPR20_CONTAINER _Container_proxy_ptr12(_Alloc& _Al_, _Leave_proxy_unbound) : _Al(_Al_) { // create a new unbound _Container_proxy _Ptr = _Unfancy(_Al_.allocate(1)); _Construct_in_place(*_Ptr); } - _CONSTEXPR20_DYNALLOC _Container_proxy_ptr12(_Alloc& _Al_, _Container_base12& _Mycont) : _Al(_Al_) { + _CONSTEXPR20_CONTAINER _Container_proxy_ptr12(_Alloc& _Al_, _Container_base12& _Mycont) : _Al(_Al_) { // create a new _Container_proxy pointing at _Mycont _Ptr = _Unfancy(_Al_.allocate(1)); _Construct_in_place(*_Ptr, _STD addressof(_Mycont)); _Mycont._Myproxy = _Ptr; } - _CONSTEXPR20_DYNALLOC void _Bind(_Alloc& _Old_alloc, _Container_base12* _Mycont) noexcept { + _CONSTEXPR20_CONTAINER void _Bind(_Alloc& _Old_alloc, _Container_base12* _Mycont) noexcept { // Attach the proxy stored in *this to _Mycont, and destroy _Mycont's existing proxy // with _Old_alloc. Requires that no iterators are alive referring to _Mycont. _Ptr->_Mycont = _Mycont; _Delete_plain_internal(_Old_alloc, _STD exchange(_Mycont->_Myproxy, _STD exchange(_Ptr, nullptr))); } - _CONSTEXPR20_DYNALLOC ~_Container_proxy_ptr12() { + _CONSTEXPR20_CONTAINER ~_Container_proxy_ptr12() { if (_Ptr) { _Delete_plain_internal(_Al, _Ptr); } diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index e37d8daf036..b5d3d18f968 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -1263,6 +1263,13 @@ #define _CONSTEXPR20_DYNALLOC inline #endif +// Functions that became constexpr in C++20 via P0980R1 or P1004R2 +#if defined(__cpp_lib_constexpr_dynamic_alloc) && !defined(__clang__) // TRANSITION:LLVM-48606 +#define _CONSTEXPR20_CONTAINER constexpr +#else +#define _CONSTEXPR20_CONTAINER inline +#endif + #ifdef _RTC_CONVERSION_CHECKS_ENABLED #ifndef _ALLOW_RTCc_IN_STL #error /RTCc rejects conformant code, so it is not supported by the C++ Standard Library. Either remove this \ From 4135658ef61bdc2d1d2d43a3023caebd94af2a27 Mon Sep 17 00:00:00 2001 From: Michael Schellenberger Costa Date: Thu, 21 Jan 2021 22:22:25 +0100 Subject: [PATCH 04/50] Address review comments --- stl/inc/regex | 2 +- stl/inc/xmemory | 44 +++++++++++++++++++++----------------------- stl/inc/xutility | 2 +- 3 files changed, 23 insertions(+), 25 deletions(-) diff --git a/stl/inc/regex b/stl/inc/regex index 0cd17c2b3a0..330944b8a28 100644 --- a/stl/inc/regex +++ b/stl/inc/regex @@ -2466,7 +2466,7 @@ public: _MyRe = nullptr; #if _ITERATOR_DEBUG_LEVEL == 2 - this->_Orphan_me(); + this->_Orphan_me_v2(); #endif // _ITERATOR_DEBUG_LEVEL return *this; diff --git a/stl/inc/xmemory b/stl/inc/xmemory index 3497438a30a..61872788623 100644 --- a/stl/inc/xmemory +++ b/stl/inc/xmemory @@ -265,10 +265,10 @@ _CONSTEXPR20_DYNALLOC void _Deallocate(void* _Ptr, size_t _Bytes) noexcept { // FUNCTION TEMPLATE _Global_new template -_CONSTEXPR20_DYNALLOC _Ty* _Global_new(_Types&&... _Args) { // acts as "new" while disallowing user overload selection +_Ty* _Global_new(_Types&&... _Args) { // acts as "new" while disallowing user overload selection struct _NODISCARD _Guard_type { void* _Result; - _CONSTEXPR20_DYNALLOC ~_Guard_type() { + ~_Guard_type() { if (_Result) { _Deallocate<_New_alignof<_Ty>>(_Result, sizeof(_Ty)); } @@ -991,7 +991,7 @@ struct _Alloc_construct_ptr { // pointer used to help construct 1 _Alloc::value_ _Alloc& _Al; pointer _Ptr; - explicit _Alloc_construct_ptr(_Alloc& _Al_) : _Al(_Al_), _Ptr(nullptr) {} + _CONSTEXPR20_DYNALLOC explicit _Alloc_construct_ptr(_Alloc& _Al_) : _Al(_Al_), _Ptr(nullptr) {} _NODISCARD _CONSTEXPR20_DYNALLOC pointer _Release() noexcept { // disengage *this and return contained pointer return _STD exchange(_Ptr, nullptr); @@ -1072,9 +1072,17 @@ public: private: _CONSTEXPR20_CONTAINER void _Orphan_all_unlocked() noexcept; - inline void _Orphan_all_locked() noexcept; _CONSTEXPR20_CONTAINER void _Swap_proxy_and_iterators_unlocked(_Container_base12&) noexcept; - inline void _Swap_proxy_and_iterators_locked(_Container_base12&) noexcept; + + void _Orphan_all_locked() noexcept { + _Lockit _Lock(_LOCK_DEBUG); + _Orphan_all_unlocked(); + } + + void _Swap_proxy_and_iterators_locked(_Container_base12& _Right) noexcept { + _Lockit _Lock(_LOCK_DEBUG); + _Swap_proxy_and_iterators_unlocked(_Right); + } }; struct _Iterator_base12 { // store links to container proxy, next iterator @@ -1091,7 +1099,7 @@ public: _Adopt(_Right._Myproxy->_Mycont); } else { // becoming invalid, disown current parent #if _ITERATOR_DEBUG_LEVEL == 2 - _Orphan_me(); + _Orphan_me_v2(); #else // _ITERATOR_DEBUG_LEVEL == 2 _Myproxy = nullptr; #endif // _ITERATOR_DEBUG_LEVEL == 2 @@ -1102,7 +1110,7 @@ public: #if _ITERATOR_DEBUG_LEVEL == 2 _CONSTEXPR20_CONTAINER ~_Iterator_base12() noexcept { - _Orphan_me(); + _Orphan_me_v2(); } _CONSTEXPR20_CONTAINER void _Adopt(const _Container_base12* _Parent) noexcept { @@ -1119,11 +1127,11 @@ public: } } } else { // no future parent, just disown current parent - _Orphan_me(); + _Orphan_me_v2(); } } - _CONSTEXPR20_CONTAINER void _Orphan_me() noexcept { + _CONSTEXPR20_CONTAINER void _Orphan_me_v2() noexcept { if (_Myproxy) { // adopted, remove self from list #ifdef __cpp_lib_is_constant_evaluated if (_STD is_constant_evaluated()) { @@ -1197,11 +1205,6 @@ _CONSTEXPR20_CONTAINER void _Container_base12::_Orphan_all_unlocked() noexcept { _Myproxy->_Myfirstiter = nullptr; } -inline void _Container_base12::_Orphan_all_locked() noexcept { - _Lockit _Lock(_LOCK_DEBUG); - _Orphan_all_unlocked(); -} - _CONSTEXPR20_CONTAINER void _Container_base12::_Orphan_all() noexcept { #if _ITERATOR_DEBUG_LEVEL == 2 if (_Myproxy) { // proxy allocated, drain it @@ -1231,15 +1234,8 @@ _CONSTEXPR20_CONTAINER void _Container_base12::_Swap_proxy_and_iterators_unlocke } } -inline void _Container_base12::_Swap_proxy_and_iterators_locked(_Container_base12& _Right) noexcept { - _Lockit _Lock(_LOCK_DEBUG); - _Swap_proxy_and_iterators_unlocked(_Right); -} - _CONSTEXPR20_CONTAINER void _Container_base12::_Swap_proxy_and_iterators(_Container_base12& _Right) noexcept { -#if _ITERATOR_DEBUG_LEVEL != 2 - _Swap_proxy_and_iterators_unlocked(_Right); -#else // ^^^ _ITERATOR_DEBUG_LEVEL != 2 ^^^ / vvv _ITERATOR_DEBUG_LEVEL == 2 vvv +#if _ITERATOR_DEBUG_LEVEL == 2 #ifdef __cpp_lib_is_constant_evaluated if (_STD is_constant_evaluated()) { _Swap_proxy_and_iterators_unlocked(_Right); @@ -1248,7 +1244,9 @@ _CONSTEXPR20_CONTAINER void _Container_base12::_Swap_proxy_and_iterators(_Contai { _Swap_proxy_and_iterators_locked(_Right); } -#endif // _ITERATOR_DEBUG_LEVEL == 2 +#else // ^^^ _ITERATOR_DEBUG_LEVEL == 2 ^^^ / vvv _ITERATOR_DEBUG_LEVEL != 2 vvv + _Swap_proxy_and_iterators_unlocked(_Right); +#endif // _ITERATOR_DEBUG_LEVEL != 2 } #if _ITERATOR_DEBUG_LEVEL == 0 diff --git a/stl/inc/xutility b/stl/inc/xutility index 56b05526b87..2264dfb0a0f 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -155,7 +155,7 @@ _CONSTEXPR20_DYNALLOC void _Construct_in_place(_Ty& _Obj, _Types&&... _Args) noe // FUNCTION TEMPLATE _Default_construct_in_place template -_CONSTEXPR20_DYNALLOC void _Default_construct_in_place(_Ty& _Obj) noexcept(is_nothrow_default_constructible_v<_Ty>) { +void _Default_construct_in_place(_Ty& _Obj) noexcept(is_nothrow_default_constructible_v<_Ty>) { ::new (_Voidify_iter(_STD addressof(_Obj))) _Ty; } From 3000309ec78683a2d7f8495dd0e1c2f1ce528d3a Mon Sep 17 00:00:00 2001 From: Michael Schellenberger Costa Date: Fri, 22 Jan 2021 08:45:03 +0100 Subject: [PATCH 05/50] Unblock __cpp_lib_constexpr_dynamic_alloc for all compilers that suppport constexpr allocations --- stl/inc/xmemory | 2 +- stl/inc/yvals_core.h | 5 ++--- .../VSO_0157762_feature_test_macros/test.compile.pass.cpp | 3 +-- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/stl/inc/xmemory b/stl/inc/xmemory index 61872788623..e8fcb9f4397 100644 --- a/stl/inc/xmemory +++ b/stl/inc/xmemory @@ -1274,7 +1274,7 @@ struct _Fake_proxy_ptr_impl { // fake replacement for a container proxy smart po struct _Basic_container_proxy_ptr12 { // smart pointer components for a _Container_proxy * that don't depend on the allocator - _Container_proxy* _Ptr; + _Container_proxy* _Ptr = nullptr; constexpr void _Release() noexcept { // disengage this _Basic_container_proxy_ptr12 _Ptr = nullptr; diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index b5d3d18f968..72b2d93e095 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -1183,10 +1183,9 @@ #define __cpp_lib_constexpr_algorithms 201806L #define __cpp_lib_constexpr_complex 201711L -#if defined(__cpp_constexpr_dynamic_alloc) \ - && defined(__clang__) // TRANSITION, MSVC support for constexpr dynamic allocation +#ifdef __cpp_constexpr_dynamic_alloc #define __cpp_lib_constexpr_dynamic_alloc 201907L -#endif // defined(__cpp_constexpr_dynamic_alloc) && defined(__clang__) +#endif // __cpp_constexpr_dynamic_alloc #define __cpp_lib_constexpr_functional 201907L #define __cpp_lib_constexpr_iterator 201811L diff --git a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp index 9a6cd10c972..1aa7807505b 100644 --- a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp +++ b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp @@ -411,8 +411,7 @@ STATIC_ASSERT(__cpp_lib_constexpr_complex == 201711L); #endif #endif -#if _HAS_CXX20 && defined(__cpp_constexpr_dynamic_alloc) \ - && defined(__clang__) // TRANSITION, MSVC support for constexpr dynamic allocation +#if _HAS_CXX20 && defined(__cpp_constexpr_dynamic_alloc) #ifndef __cpp_lib_constexpr_dynamic_alloc #error __cpp_lib_constexpr_dynamic_alloc is not defined #elif __cpp_lib_constexpr_dynamic_alloc != 201907L From 593de17cd32036309f3a011d3a79c6e22e50f102 Mon Sep 17 00:00:00 2001 From: Michael Schellenberger Costa Date: Fri, 22 Jan 2021 12:25:32 +0100 Subject: [PATCH 06/50] Unskip some tests --- tests/libcxx/expected_results.txt | 9 --------- tests/libcxx/skipped_tests.txt | 9 --------- 2 files changed, 18 deletions(-) diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index 8961a1cc341..fbcaa710309 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -493,18 +493,9 @@ std/utilities/variant/variant.variant/variant.ctor/conv.pass.cpp FAIL std/utilities/variant/variant.variant/variant.ctor/T.pass.cpp FAIL # C++20 P0784R7 "More constexpr containers" -std/utilities/memory/allocator.traits/allocator.traits.members/allocate.pass.cpp:0 FAIL -std/utilities/memory/allocator.traits/allocator.traits.members/allocate_hint.pass.cpp:0 FAIL std/utilities/memory/allocator.traits/allocator.traits.members/construct.pass.cpp FAIL -std/utilities/memory/allocator.traits/allocator.traits.members/deallocate.pass.cpp:0 FAIL std/utilities/memory/allocator.traits/allocator.traits.members/destroy.pass.cpp FAIL -std/utilities/memory/allocator.traits/allocator.traits.members/max_size.pass.cpp:0 FAIL -std/utilities/memory/allocator.traits/allocator.traits.members/select_on_container_copy_construction.pass.cpp:0 FAIL -std/utilities/memory/default.allocator/allocator.globals/eq.pass.cpp:0 FAIL std/utilities/memory/specialized.algorithms/specialized.construct/construct_at.pass.cpp FAIL -std/utilities/memory/specialized.algorithms/specialized.destroy/destroy.pass.cpp:0 FAIL -std/utilities/memory/specialized.algorithms/specialized.destroy/destroy_at.pass.cpp:0 FAIL -std/utilities/memory/specialized.algorithms/specialized.destroy/destroy_n.pass.cpp:0 FAIL # C++20 P0896R4 "" std/language.support/support.limits/support.limits.general/algorithm.version.pass.cpp FAIL diff --git a/tests/libcxx/skipped_tests.txt b/tests/libcxx/skipped_tests.txt index 61b46acc242..91eeaae1370 100644 --- a/tests/libcxx/skipped_tests.txt +++ b/tests/libcxx/skipped_tests.txt @@ -493,18 +493,9 @@ utilities\variant\variant.variant\variant.ctor\conv.pass.cpp utilities\variant\variant.variant\variant.ctor\T.pass.cpp # C++20 P0784R7 "More constexpr containers" -utilities\memory\allocator.traits\allocator.traits.members\allocate.pass.cpp -utilities\memory\allocator.traits\allocator.traits.members\allocate_hint.pass.cpp utilities\memory\allocator.traits\allocator.traits.members\construct.pass.cpp -utilities\memory\allocator.traits\allocator.traits.members\deallocate.pass.cpp utilities\memory\allocator.traits\allocator.traits.members\destroy.pass.cpp -utilities\memory\allocator.traits\allocator.traits.members\max_size.pass.cpp -utilities\memory\allocator.traits\allocator.traits.members\select_on_container_copy_construction.pass.cpp -utilities\memory\default.allocator\allocator.globals\eq.pass.cpp utilities\memory\specialized.algorithms\specialized.construct\construct_at.pass.cpp -utilities\memory\specialized.algorithms\specialized.destroy\destroy.pass.cpp -utilities\memory\specialized.algorithms\specialized.destroy\destroy_at.pass.cpp -utilities\memory\specialized.algorithms\specialized.destroy\destroy_n.pass.cpp # C++20 P0896R4 "" language.support\support.limits\support.limits.general\algorithm.version.pass.cpp From 5e56275e5081524129ef089e1ed0917cae3f07c6 Mon Sep 17 00:00:00 2001 From: Michael Schellenberger Costa Date: Fri, 22 Jan 2021 12:34:18 +0100 Subject: [PATCH 07/50] Consistently use __cpp_lib_constexpr_dynamic_alloc --- stl/inc/xmemory | 44 ++++++++++++++++++++++---------------------- stl/inc/xutility | 4 ++-- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/stl/inc/xmemory b/stl/inc/xmemory index e8fcb9f4397..58823353f0a 100644 --- a/stl/inc/xmemory +++ b/stl/inc/xmemory @@ -1117,11 +1117,11 @@ public: if (_Parent) { // have a parent, do adoption _Container_proxy* _Parent_proxy = _Parent->_Myproxy; if (_Myproxy != _Parent_proxy) { // change parentage -#ifdef __cpp_lib_is_constant_evaluated +#ifdef __cpp_lib_constexpr_dynamic_alloc if (_STD is_constant_evaluated()) { _Adopt_unlocked(_Parent_proxy); } else -#endif // __cpp_lib_is_constant_evaluated +#endif // __cpp_lib_constexpr_dynamic_alloc { _Adopt_locked(_Parent_proxy); } @@ -1133,11 +1133,11 @@ public: _CONSTEXPR20_CONTAINER void _Orphan_me_v2() noexcept { if (_Myproxy) { // adopted, remove self from list -#ifdef __cpp_lib_is_constant_evaluated +#ifdef __cpp_lib_constexpr_dynamic_alloc if (_STD is_constant_evaluated()) { _Orphan_me_unlocked(); } else -#endif // __cpp_lib_is_constant_evaluated +#endif // __cpp_lib_constexpr_dynamic_alloc { _Orphan_me_locked(); } @@ -1208,11 +1208,11 @@ _CONSTEXPR20_CONTAINER void _Container_base12::_Orphan_all_unlocked() noexcept { _CONSTEXPR20_CONTAINER void _Container_base12::_Orphan_all() noexcept { #if _ITERATOR_DEBUG_LEVEL == 2 if (_Myproxy) { // proxy allocated, drain it -#ifdef __cpp_lib_is_constant_evaluated +#ifdef __cpp_lib_constexpr_dynamic_alloc if (_STD is_constant_evaluated()) { _Orphan_all_unlocked(); } else -#endif // __cpp_lib_is_constant_evaluated +#endif // __cpp_lib_constexpr_dynamic_alloc { _Orphan_all_locked(); } @@ -1236,11 +1236,11 @@ _CONSTEXPR20_CONTAINER void _Container_base12::_Swap_proxy_and_iterators_unlocke _CONSTEXPR20_CONTAINER void _Container_base12::_Swap_proxy_and_iterators(_Container_base12& _Right) noexcept { #if _ITERATOR_DEBUG_LEVEL == 2 -#ifdef __cpp_lib_is_constant_evaluated +#ifdef __cpp_lib_constexpr_dynamic_alloc if (_STD is_constant_evaluated()) { _Swap_proxy_and_iterators_unlocked(_Right); } else -#endif // __cpp_lib_is_constant_evaluated +#endif // __cpp_lib_constexpr_dynamic_alloc { _Swap_proxy_and_iterators_locked(_Right); } @@ -1492,9 +1492,9 @@ _CONSTEXPR20_DYNALLOC _NoThrowFwdIt _Uninitialized_move_unchecked( _InIt _First, const _InIt _Last, _NoThrowFwdIt _Dest) { // move [_First, _Last) to raw [_Dest, ...) if constexpr (_Ptr_move_cat<_InIt, _NoThrowFwdIt>::_Really_trivial) { -#ifdef __cpp_lib_is_constant_evaluated +#ifdef __cpp_lib_constexpr_dynamic_alloc if (!_STD is_constant_evaluated()) -#endif // __cpp_lib_is_constant_evaluated +#endif // __cpp_lib_constexpr_dynamic_alloc { return _Copy_memmove(_First, _Last, _Dest); } @@ -1554,9 +1554,9 @@ _CONSTEXPR20_DYNALLOC _Alloc_ptr_t<_Alloc> _Uninitialized_copy( if constexpr (conjunction_v::_Really_trivial>, _Uses_default_construct<_Alloc, _Ptrval, decltype(*_UFirst)>>) { -#ifdef __cpp_lib_is_constant_evaluated +#ifdef __cpp_lib_constexpr_dynamic_alloc if (!_STD is_constant_evaluated()) -#endif // __cpp_lib_is_constant_evaluated +#endif // __cpp_lib_constexpr_dynamic_alloc { _Copy_memmove(_UFirst, _ULast, _Unfancy(_Dest)); _Dest += _ULast - _UFirst; @@ -1579,9 +1579,9 @@ _CONSTEXPR20_DYNALLOC _NoThrowFwdIt _Uninitialized_copy_unchecked( _InIt _First, const _InIt _Last, _NoThrowFwdIt _Dest) { // copy [_First, _Last) to raw [_Dest, ...) if constexpr (_Ptr_move_cat<_InIt, _NoThrowFwdIt>::_Really_trivial) { -#ifdef __cpp_lib_is_constant_evaluated +#ifdef __cpp_lib_constexpr_dynamic_alloc if (!_STD is_constant_evaluated()) -#endif // __cpp_lib_is_constant_evaluated +#endif // __cpp_lib_constexpr_dynamic_alloc { return _Copy_memmove(_First, _Last, _Dest); } @@ -1618,9 +1618,9 @@ _CONSTEXPR20_DYNALLOC _Alloc_ptr_t<_Alloc> _Uninitialized_move( const auto _ULast = _Get_unwrapped(_Last); if constexpr (conjunction_v::_Really_trivial>, _Uses_default_construct<_Alloc, _Ptrval, decltype(_STD move(*_UFirst))>>) { -#ifdef __cpp_lib_is_constant_evaluated +#ifdef __cpp_lib_constexpr_dynamic_alloc if (!_STD is_constant_evaluated()) -#endif // __cpp_lib_is_constant_evaluated +#endif // __cpp_lib_constexpr_dynamic_alloc { _Copy_memmove(_UFirst, _ULast, _Unfancy(_Dest)); return _Dest + (_ULast - _UFirst); @@ -1641,17 +1641,17 @@ _CONSTEXPR20_DYNALLOC _Alloc_ptr_t<_Alloc> _Uninitialized_fill_n( // copy _Count copies of _Val to raw _First, using _Al using _Ty = typename _Alloc::value_type; if constexpr (_Fill_memset_is_safe<_Ty*, _Ty> && _Uses_default_construct<_Alloc, _Ty*, _Ty>::value) { -#ifdef __cpp_lib_is_constant_evaluated +#ifdef __cpp_lib_constexpr_dynamic_alloc if (!_STD is_constant_evaluated()) -#endif // __cpp_lib_is_constant_evaluated +#endif // __cpp_lib_constexpr_dynamic_alloc { _Fill_memset(_Unfancy(_First), _Val, static_cast(_Count)); return _First + _Count; } } else if constexpr (_Fill_zero_memset_is_safe<_Ty*, _Ty> && _Uses_default_construct<_Alloc, _Ty*, _Ty>::value) { -#ifdef __cpp_lib_is_constant_evaluated +#ifdef __cpp_lib_constexpr_dynamic_alloc if (!_STD is_constant_evaluated()) -#endif // __cpp_lib_is_constant_evaluated +#endif // __cpp_lib_constexpr_dynamic_alloc { if (_Is_all_bits_zero(_Val)) { _Fill_zero_memset(_Unfancy(_First), static_cast(_Count)); @@ -1713,9 +1713,9 @@ _CONSTEXPR20_DYNALLOC _Alloc_ptr_t<_Alloc> _Uninitialized_value_construct_n( // value-initialize _Count objects to raw _First, using _Al using _Ptrty = typename _Alloc::value_type*; if constexpr (_Use_memset_value_construct_v<_Ptrty> && _Uses_default_construct<_Alloc, _Ptrty>::value) { -#ifdef __cpp_lib_is_constant_evaluated +#ifdef __cpp_lib_constexpr_dynamic_alloc if (!_STD is_constant_evaluated()) -#endif // __cpp_lib_is_constant_evaluated +#endif // __cpp_lib_constexpr_dynamic_alloc { auto _PFirst = _Unfancy(_First); _Zero_range(_PFirst, _PFirst + _Count); diff --git a/stl/inc/xutility b/stl/inc/xutility index 2264dfb0a0f..8c223caa7a9 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -143,11 +143,11 @@ _CONSTEXPR20_DYNALLOC auto construct_at(_Ty* const _Location, _Types&&... _Args) template _CONSTEXPR20_DYNALLOC void _Construct_in_place(_Ty& _Obj, _Types&&... _Args) noexcept( is_nothrow_constructible_v<_Ty, _Types...>) { -#ifdef __cpp_lib_is_constant_evaluated +#ifdef __cpp_lib_constexpr_dynamic_alloc if (_STD is_constant_evaluated()) { _STD construct_at(_STD addressof(_Obj), _STD forward<_Types>(_Args)...); } else -#endif // __cpp_lib_is_constant_evaluated +#endif // __cpp_lib_constexpr_dynamic_alloc { ::new (_Voidify_iter(_STD addressof(_Obj))) _Ty(_STD forward<_Types>(_Args)...); } From ed8c2dc303af03661793a9510cbcd8631eec17fa Mon Sep 17 00:00:00 2001 From: Michael Schellenberger Costa Date: Fri, 22 Jan 2021 13:59:30 +0100 Subject: [PATCH 08/50] Properly guard ranges in tests --- .../test.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/std/tests/P0784R7_library_support_for_more_constexpr_containers/test.cpp b/tests/std/tests/P0784R7_library_support_for_more_constexpr_containers/test.cpp index 52da34b9f96..08a4de3ae07 100644 --- a/tests/std/tests/P0784R7_library_support_for_more_constexpr_containers/test.cpp +++ b/tests/std/tests/P0784R7_library_support_for_more_constexpr_containers/test.cpp @@ -244,9 +244,11 @@ constexpr void test_compiletime() { assert(s.object == 42); destroy_at(&s.object); +#ifdef __cpp_lib_concepts ranges::construct_at(&s.object, 1729); assert(s.object == 1729); ranges::destroy_at(&s.object); +#endif // __cpp_lib_concepts } struct nontrivial { @@ -262,9 +264,11 @@ constexpr void test_compiletime() { assert(s.object.x == 42); destroy_at(&s.object); +#ifdef __cpp_lib_concepts ranges::construct_at(&s.object, 1729); assert(s.object.x == 1729); ranges::destroy_at(&s.object); +#endif // __cpp_lib_concepts } } static_assert((test_compiletime(), true)); From 5d393af304c37fb83bda7d7f2509495f60557037 Mon Sep 17 00:00:00 2001 From: Miya Natsuhara Date: Wed, 27 Jan 2021 11:43:24 -0800 Subject: [PATCH 09/50] Disable portions of P0784 test for EDG due to bugs --- .../test.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/std/tests/P0784R7_library_support_for_more_constexpr_containers/test.cpp b/tests/std/tests/P0784R7_library_support_for_more_constexpr_containers/test.cpp index 08a4de3ae07..33a9fd23026 100644 --- a/tests/std/tests/P0784R7_library_support_for_more_constexpr_containers/test.cpp +++ b/tests/std/tests/P0784R7_library_support_for_more_constexpr_containers/test.cpp @@ -227,6 +227,7 @@ void test_array(const T& val) { } #ifdef __cpp_lib_constexpr_dynamic_alloc +#ifndef __EDG__ // TRANSITION, VSO-1269976 template struct storage_for { union { @@ -272,6 +273,7 @@ constexpr void test_compiletime() { } } static_assert((test_compiletime(), true)); +#endif // __EDG__ template struct A { @@ -289,7 +291,9 @@ struct nontrivial_A { constexpr ~nontrivial_A() {} }; + constexpr void test_compiletime_destroy_variants() { +#ifndef __EDG__ // TRANSITION, VSO-1270011 { allocator> alloc{}; A* a = alloc.allocate(10); @@ -308,6 +312,7 @@ constexpr void test_compiletime_destroy_variants() { destroy(a, a + 10); alloc.deallocate(a, 10); } +#endif // __EDG__ #ifdef __cpp_lib_concepts { allocator> alloc{}; @@ -389,6 +394,7 @@ constexpr void test_compiletime_destroy_variants() { } static_assert((test_compiletime_destroy_variants(), true)); +#ifndef __EDG__ // TRANSITION, VSO-1269976 template struct Alloc { using value_type = T; @@ -502,6 +508,7 @@ constexpr void test_compiletime_allocator_traits() { } } static_assert((test_compiletime_allocator_traits(), true)); +#endif // __EDG__ constexpr void test_compiletime_allocator() { { From b3140a49ab7fd679d55efc43862da517ad671fac Mon Sep 17 00:00:00 2001 From: Michael Schellenberger Costa Date: Fri, 29 Jan 2021 07:03:29 +0100 Subject: [PATCH 10/50] Try to apply workaround --- stl/inc/xmemory | 3 ++- .../test.cpp | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/xmemory b/stl/inc/xmemory index 58823353f0a..082cae0c57b 100644 --- a/stl/inc/xmemory +++ b/stl/inc/xmemory @@ -1182,7 +1182,8 @@ private: _CONSTEXPR20_CONTAINER void _Orphan_me_unlocked() noexcept { _Iterator_base12** _Pnext = &_Myproxy->_Myfirstiter; while (*_Pnext && *_Pnext != this) { - _Pnext = &(*_Pnext)->_Mynextiter; + const auto _Temp = *_Pnext; // TRANSITION: ASO-XXXXX + _Pnext = &_Temp->_Mynextiter; } _STL_VERIFY(*_Pnext, "ITERATOR LIST CORRUPTED!"); diff --git a/tests/std/tests/P0784R7_library_support_for_more_constexpr_containers/test.cpp b/tests/std/tests/P0784R7_library_support_for_more_constexpr_containers/test.cpp index 33a9fd23026..7939af14b21 100644 --- a/tests/std/tests/P0784R7_library_support_for_more_constexpr_containers/test.cpp +++ b/tests/std/tests/P0784R7_library_support_for_more_constexpr_containers/test.cpp @@ -291,7 +291,6 @@ struct nontrivial_A { constexpr ~nontrivial_A() {} }; - constexpr void test_compiletime_destroy_variants() { #ifndef __EDG__ // TRANSITION, VSO-1270011 { From d6f948d1321dcbe94f597c0f5bfd46ad017897e3 Mon Sep 17 00:00:00 2001 From: Michael Schellenberger Costa Date: Fri, 29 Jan 2021 12:31:06 +0100 Subject: [PATCH 11/50] [P10042R2] Implement constexpr vector Fixes #45 --- stl/inc/vector | 1072 ++++++++++------- stl/inc/yvals_core.h | 5 + tests/std/test.lst | 3 + .../tests/P0784R7_library_machinery/env.lst | 4 + .../tests/P0784R7_library_machinery/test.cpp | 147 +++ .../tests/P1004R2_constexpr_vector/env.lst | 4 + .../tests/P1004R2_constexpr_vector/test.cpp | 638 ++++++++++ .../P1004R2_constexpr_vector_bool/env.lst | 4 + .../P1004R2_constexpr_vector_bool/test.cpp | 538 +++++++++ 9 files changed, 1990 insertions(+), 425 deletions(-) create mode 100644 tests/std/tests/P0784R7_library_machinery/env.lst create mode 100644 tests/std/tests/P0784R7_library_machinery/test.cpp create mode 100644 tests/std/tests/P1004R2_constexpr_vector/env.lst create mode 100644 tests/std/tests/P1004R2_constexpr_vector/test.cpp create mode 100644 tests/std/tests/P1004R2_constexpr_vector_bool/env.lst create mode 100644 tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp diff --git a/stl/inc/vector b/stl/inc/vector index fe53326da9f..5fe858a6897 100644 --- a/stl/inc/vector +++ b/stl/inc/vector @@ -37,161 +37,199 @@ public: using _Tptr = typename _Myvec::pointer; - _Vector_const_iterator() noexcept : _Ptr() {} + _CONSTEXPR20_CONTAINER _Vector_const_iterator() noexcept : _Ptr() {} - _Vector_const_iterator(_Tptr _Parg, const _Container_base* _Pvector) noexcept : _Ptr(_Parg) { + _CONSTEXPR20_CONTAINER _Vector_const_iterator(_Tptr _Parg, const _Container_base* _Pvector) noexcept : _Ptr(_Parg) { this->_Adopt(_Pvector); } - _NODISCARD reference operator*() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER reference operator*() const noexcept { #if _ITERATOR_DEBUG_LEVEL != 0 - const auto _Mycont = static_cast(this->_Getcont()); - _STL_VERIFY(_Ptr, "can't dereference value-initialized vector iterator"); - _STL_VERIFY( - _Mycont->_Myfirst <= _Ptr && _Ptr < _Mycont->_Mylast, "can't dereference out of range vector iterator"); +#ifdef __cpp_lib_constexpr_dynamic_alloc + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_constexpr_dynamic_alloc + { + const auto _Mycont = static_cast(this->_Getcont()); + _STL_VERIFY(_Ptr, "can't dereference value-initialized vector iterator"); + _STL_VERIFY( + _Mycont->_Myfirst <= _Ptr && _Ptr < _Mycont->_Mylast, "can't dereference out of range vector iterator"); + } #endif // _ITERATOR_DEBUG_LEVEL != 0 return *_Ptr; } - _NODISCARD pointer operator->() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER pointer operator->() const noexcept { #if _ITERATOR_DEBUG_LEVEL != 0 - const auto _Mycont = static_cast(this->_Getcont()); - _STL_VERIFY(_Ptr, "can't dereference value-initialized vector iterator"); - _STL_VERIFY( - _Mycont->_Myfirst <= _Ptr && _Ptr < _Mycont->_Mylast, "can't dereference out of range vector iterator"); +#ifdef __cpp_lib_constexpr_dynamic_alloc + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_constexpr_dynamic_alloc + { + const auto _Mycont = static_cast(this->_Getcont()); + _STL_VERIFY(_Ptr, "can't dereference value-initialized vector iterator"); + _STL_VERIFY( + _Mycont->_Myfirst <= _Ptr && _Ptr < _Mycont->_Mylast, "can't dereference out of range vector iterator"); + } #endif // _ITERATOR_DEBUG_LEVEL != 0 return _Ptr; } - _Vector_const_iterator& operator++() noexcept { + _CONSTEXPR20_CONTAINER _Vector_const_iterator& operator++() noexcept { #if _ITERATOR_DEBUG_LEVEL != 0 - const auto _Mycont = static_cast(this->_Getcont()); - _STL_VERIFY(_Ptr, "can't increment value-initialized vector iterator"); - _STL_VERIFY(_Ptr < _Mycont->_Mylast, "can't increment vector iterator past end"); +#ifdef __cpp_lib_constexpr_dynamic_alloc + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_constexpr_dynamic_alloc + { + const auto _Mycont = static_cast(this->_Getcont()); + _STL_VERIFY(_Ptr, "can't increment value-initialized vector iterator"); + _STL_VERIFY(_Ptr < _Mycont->_Mylast, "can't increment vector iterator past end"); + } #endif // _ITERATOR_DEBUG_LEVEL != 0 ++_Ptr; return *this; } - _Vector_const_iterator operator++(int) noexcept { + _CONSTEXPR20_CONTAINER _Vector_const_iterator operator++(int) noexcept { _Vector_const_iterator _Tmp = *this; ++*this; return _Tmp; } - _Vector_const_iterator& operator--() noexcept { + _CONSTEXPR20_CONTAINER _Vector_const_iterator& operator--() noexcept { #if _ITERATOR_DEBUG_LEVEL != 0 - const auto _Mycont = static_cast(this->_Getcont()); - _STL_VERIFY(_Ptr, "can't decrement value-initialized vector iterator"); - _STL_VERIFY(_Mycont->_Myfirst < _Ptr, "can't decrement vector iterator before begin"); +#ifdef __cpp_lib_constexpr_dynamic_alloc + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_constexpr_dynamic_alloc + { + const auto _Mycont = static_cast(this->_Getcont()); + _STL_VERIFY(_Ptr, "can't decrement value-initialized vector iterator"); + _STL_VERIFY(_Mycont->_Myfirst < _Ptr, "can't decrement vector iterator before begin"); + } #endif // _ITERATOR_DEBUG_LEVEL != 0 --_Ptr; return *this; } - _Vector_const_iterator operator--(int) noexcept { + _CONSTEXPR20_CONTAINER _Vector_const_iterator operator--(int) noexcept { _Vector_const_iterator _Tmp = *this; --*this; return _Tmp; } - void _Verify_offset(const difference_type _Off) const noexcept { + _CONSTEXPR20_CONTAINER void _Verify_offset(const difference_type _Off) const noexcept { #if _ITERATOR_DEBUG_LEVEL == 0 (void) _Off; #else // ^^^ _ITERATOR_DEBUG_LEVEL == 0 ^^^ // vvv _ITERATOR_DEBUG_LEVEL != 0 vvv - const auto _Mycont = static_cast(this->_Getcont()); - _STL_VERIFY(_Off == 0 || _Ptr, "cannot seek value-initialized vector iterator"); - if (_Off < 0) { - _STL_VERIFY(_Off >= _Mycont->_Myfirst - _Ptr, "cannot seek vector iterator before begin"); - } +#ifdef __cpp_lib_constexpr_dynamic_alloc + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_constexpr_dynamic_alloc + { + const auto _Mycont = static_cast(this->_Getcont()); + _STL_VERIFY(_Off == 0 || _Ptr, "cannot seek value-initialized vector iterator"); + if (_Off < 0) { + _STL_VERIFY(_Off >= _Mycont->_Myfirst - _Ptr, "cannot seek vector iterator before begin"); + } - if (_Off > 0) { - _STL_VERIFY(_Off <= _Mycont->_Mylast - _Ptr, "cannot seek vector iterator after end"); + if (_Off > 0) { + _STL_VERIFY(_Off <= _Mycont->_Mylast - _Ptr, "cannot seek vector iterator after end"); + } } #endif // _ITERATOR_DEBUG_LEVEL == 0 } - _Vector_const_iterator& operator+=(const difference_type _Off) noexcept { + _CONSTEXPR20_CONTAINER _Vector_const_iterator& operator+=(const difference_type _Off) noexcept { _Verify_offset(_Off); _Ptr += _Off; return *this; } - _NODISCARD _Vector_const_iterator operator+(const difference_type _Off) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER _Vector_const_iterator operator+(const difference_type _Off) const noexcept { _Vector_const_iterator _Tmp = *this; return _Tmp += _Off; } - _Vector_const_iterator& operator-=(const difference_type _Off) noexcept { + _CONSTEXPR20_CONTAINER _Vector_const_iterator& operator-=(const difference_type _Off) noexcept { return *this += -_Off; } - _NODISCARD _Vector_const_iterator operator-(const difference_type _Off) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER _Vector_const_iterator operator-(const difference_type _Off) const noexcept { _Vector_const_iterator _Tmp = *this; return _Tmp -= _Off; } - _NODISCARD difference_type operator-(const _Vector_const_iterator& _Right) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER difference_type operator-(const _Vector_const_iterator& _Right) const noexcept { _Compat(_Right); return _Ptr - _Right._Ptr; } - _NODISCARD reference operator[](const difference_type _Off) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER reference operator[](const difference_type _Off) const noexcept { return *(*this + _Off); } - _NODISCARD bool operator==(const _Vector_const_iterator& _Right) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER bool operator==(const _Vector_const_iterator& _Right) const noexcept { _Compat(_Right); return _Ptr == _Right._Ptr; } - _NODISCARD bool operator!=(const _Vector_const_iterator& _Right) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER bool operator!=(const _Vector_const_iterator& _Right) const noexcept { return !(*this == _Right); } - _NODISCARD bool operator<(const _Vector_const_iterator& _Right) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER bool operator<(const _Vector_const_iterator& _Right) const noexcept { _Compat(_Right); return _Ptr < _Right._Ptr; } - _NODISCARD bool operator>(const _Vector_const_iterator& _Right) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER bool operator>(const _Vector_const_iterator& _Right) const noexcept { return _Right < *this; } - _NODISCARD bool operator<=(const _Vector_const_iterator& _Right) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER bool operator<=(const _Vector_const_iterator& _Right) const noexcept { return !(_Right < *this); } - _NODISCARD bool operator>=(const _Vector_const_iterator& _Right) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER bool operator>=(const _Vector_const_iterator& _Right) const noexcept { return !(*this < _Right); } - void _Compat(const _Vector_const_iterator& _Right) const noexcept { // test for compatible iterator pair + _CONSTEXPR20_CONTAINER void _Compat(const _Vector_const_iterator& _Right) const noexcept { + // test for compatible iterator pair #if _ITERATOR_DEBUG_LEVEL == 0 (void) _Right; #else // ^^^ _ITERATOR_DEBUG_LEVEL == 0 ^^^ // vvv _ITERATOR_DEBUG_LEVEL != 0 vvv - _STL_VERIFY(this->_Getcont() == _Right._Getcont(), "vector iterators incompatible"); +#ifdef __cpp_lib_constexpr_dynamic_alloc + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_constexpr_dynamic_alloc + { + _STL_VERIFY(this->_Getcont() == _Right._Getcont(), "vector iterators incompatible"); + } #endif // _ITERATOR_DEBUG_LEVEL == 0 } #if _ITERATOR_DEBUG_LEVEL != 0 - friend void _Verify_range(const _Vector_const_iterator& _First, const _Vector_const_iterator& _Last) noexcept { - _STL_VERIFY(_First._Getcont() == _Last._Getcont(), "vector iterators in range are from different containers"); - _STL_VERIFY(_First._Ptr <= _Last._Ptr, "vector iterator range transposed"); + friend _CONSTEXPR20_CONTAINER void _Verify_range( + const _Vector_const_iterator& _First, const _Vector_const_iterator& _Last) noexcept { +#ifdef __cpp_lib_constexpr_dynamic_alloc + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_constexpr_dynamic_alloc + { + _STL_VERIFY( + _First._Getcont() == _Last._Getcont(), "vector iterators in range are from different containers"); + _STL_VERIFY(_First._Ptr <= _Last._Ptr, "vector iterator range transposed"); + } } #endif // _ITERATOR_DEBUG_LEVEL != 0 using _Prevent_inheriting_unwrap = _Vector_const_iterator; - _NODISCARD const value_type* _Unwrapped() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER const value_type* _Unwrapped() const noexcept { return _Unfancy(_Ptr); } - void _Seek_to(const value_type* _It) noexcept { + _CONSTEXPR20_CONTAINER void _Seek_to(const value_type* _It) noexcept { _Ptr = _Refancy<_Tptr>(const_cast(_It)); } @@ -199,7 +237,7 @@ public: }; template -_NODISCARD _Vector_const_iterator<_Myvec> operator+( +_NODISCARD _CONSTEXPR20_CONTAINER _Vector_const_iterator<_Myvec> operator+( typename _Vector_const_iterator<_Myvec>::difference_type _Off, _Vector_const_iterator<_Myvec> _Next) noexcept { return _Next += _Off; } @@ -217,12 +255,17 @@ struct pointer_traits<_Vector_const_iterator<_Myvec>> { // capacity() of 0 is not. This function cannot distinguish those two cases, so it incorrectly does not diagnose // the latter. In practice, this isn't a significant problem since to_address returns nullptr for such an // iterator. - const auto _Mycont = static_cast(_Iter._Getcont()); - if (_Mycont) { - _STL_VERIFY(_Mycont->_Myfirst <= _Iter._Ptr && _Iter._Ptr <= _Mycont->_Mylast, - "can't convert out-of-range vector iterator to pointer"); - } else { - _STL_VERIFY(!_Iter._Ptr, "can't convert invalid vector iterator to pointer"); +#ifdef __cpp_lib_constexpr_dynamic_alloc + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_constexpr_dynamic_alloc + { + const auto _Mycont = static_cast(_Iter._Getcont()); + if (_Mycont) { + _STL_VERIFY(_Mycont->_Myfirst <= _Iter._Ptr && _Iter._Ptr <= _Mycont->_Mylast, + "can't convert out-of-range vector iterator to pointer"); + } else { + _STL_VERIFY(!_Iter._Ptr, "can't convert invalid vector iterator to pointer"); + } } #endif // _ITERATOR_DEBUG_LEVEL != 0 @@ -248,71 +291,83 @@ public: using _Mybase::_Mybase; - _NODISCARD reference operator*() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER reference operator*() const noexcept { return const_cast(_Mybase::operator*()); } - _NODISCARD pointer operator->() const noexcept { - return _Const_cast(_Mybase::operator->()); + _NODISCARD _CONSTEXPR20_CONTAINER pointer operator->() const noexcept { +#if _ITERATOR_DEBUG_LEVEL != 0 +#ifdef __cpp_lib_constexpr_dynamic_alloc + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_constexpr_dynamic_alloc + { + const auto _Mycont = static_cast(this->_Getcont()); + _STL_VERIFY(this->_Ptr, "can't dereference value-initialized vector iterator"); + _STL_VERIFY(_Mycont->_Myfirst <= this->_Ptr && this->_Ptr < _Mycont->_Mylast, + "can't dereference out of range vector iterator"); + } +#endif // _ITERATOR_DEBUG_LEVEL != 0 + + return this->_Ptr; } - _Vector_iterator& operator++() noexcept { + _CONSTEXPR20_CONTAINER _Vector_iterator& operator++() noexcept { _Mybase::operator++(); return *this; } - _Vector_iterator operator++(int) noexcept { + _CONSTEXPR20_CONTAINER _Vector_iterator operator++(int) noexcept { _Vector_iterator _Tmp = *this; _Mybase::operator++(); return _Tmp; } - _Vector_iterator& operator--() noexcept { + _CONSTEXPR20_CONTAINER _Vector_iterator& operator--() noexcept { _Mybase::operator--(); return *this; } - _Vector_iterator operator--(int) noexcept { + _CONSTEXPR20_CONTAINER _Vector_iterator operator--(int) noexcept { _Vector_iterator _Tmp = *this; _Mybase::operator--(); return _Tmp; } - _Vector_iterator& operator+=(const difference_type _Off) noexcept { + _CONSTEXPR20_CONTAINER _Vector_iterator& operator+=(const difference_type _Off) noexcept { _Mybase::operator+=(_Off); return *this; } - _NODISCARD _Vector_iterator operator+(const difference_type _Off) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER _Vector_iterator operator+(const difference_type _Off) const noexcept { _Vector_iterator _Tmp = *this; return _Tmp += _Off; } - _Vector_iterator& operator-=(const difference_type _Off) noexcept { + _CONSTEXPR20_CONTAINER _Vector_iterator& operator-=(const difference_type _Off) noexcept { _Mybase::operator-=(_Off); return *this; } using _Mybase::operator-; - _NODISCARD _Vector_iterator operator-(const difference_type _Off) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER _Vector_iterator operator-(const difference_type _Off) const noexcept { _Vector_iterator _Tmp = *this; return _Tmp -= _Off; } - _NODISCARD reference operator[](const difference_type _Off) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER reference operator[](const difference_type _Off) const noexcept { return const_cast(_Mybase::operator[](_Off)); } using _Prevent_inheriting_unwrap = _Vector_iterator; - _NODISCARD value_type* _Unwrapped() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER value_type* _Unwrapped() const noexcept { return _Unfancy(this->_Ptr); } }; template -_NODISCARD _Vector_iterator<_Myvec> operator+( +_NODISCARD _CONSTEXPR20_CONTAINER _Vector_iterator<_Myvec> operator+( typename _Vector_iterator<_Myvec>::difference_type _Off, _Vector_iterator<_Myvec> _Next) noexcept { return _Next += _Off; } @@ -330,12 +385,17 @@ struct pointer_traits<_Vector_iterator<_Myvec>> { // capacity() of 0 is not. This function cannot distinguish those two cases, so it incorrectly does not diagnose // the latter. In practice, this isn't a significant problem since to_address returns nullptr for such an // iterator. - const auto _Mycont = static_cast(_Iter._Getcont()); - if (_Mycont) { - _STL_VERIFY(_Mycont->_Myfirst <= _Iter._Ptr && _Iter._Ptr <= _Mycont->_Mylast, - "can't convert out-of-range vector iterator to pointer"); - } else { - _STL_VERIFY(!_Iter._Ptr, "can't convert invalid vector iterator to pointer"); +#ifdef __cpp_lib_constexpr_dynamic_alloc + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_constexpr_dynamic_alloc + { + const auto _Mycont = static_cast(_Iter._Getcont()); + if (_Mycont) { + _STL_VERIFY(_Mycont->_Myfirst <= _Iter._Ptr && _Iter._Ptr <= _Mycont->_Mylast, + "can't convert out-of-range vector iterator to pointer"); + } else { + _STL_VERIFY(!_Iter._Ptr, "can't convert invalid vector iterator to pointer"); + } } #endif // _ITERATOR_DEBUG_LEVEL != 0 @@ -372,19 +432,19 @@ public: using reference = value_type&; using const_reference = const value_type&; - _Vector_val() noexcept : _Myfirst(), _Mylast(), _Myend() {} + _CONSTEXPR20_CONTAINER _Vector_val() noexcept : _Myfirst(), _Mylast(), _Myend() {} - _Vector_val(pointer _First, pointer _Last, pointer _End) noexcept + _CONSTEXPR20_CONTAINER _Vector_val(pointer _First, pointer _Last, pointer _End) noexcept : _Myfirst(_First), _Mylast(_Last), _Myend(_End) {} - void _Swap_val(_Vector_val& _Right) noexcept { + _CONSTEXPR20_CONTAINER void _Swap_val(_Vector_val& _Right) noexcept { this->_Swap_proxy_and_iterators(_Right); _Swap_adl(_Myfirst, _Right._Myfirst); _Swap_adl(_Mylast, _Right._Mylast); _Swap_adl(_Myend, _Right._Myend); } - void _Take_contents(_Vector_val& _Right) noexcept { + _CONSTEXPR20_CONTAINER void _Take_contents(_Vector_val& _Right) noexcept { this->_Swap_proxy_and_iterators(_Right); _Myfirst = _Right._Myfirst; _Mylast = _Right._Mylast; @@ -402,12 +462,13 @@ public: // FUNCTION TEMPLATE _Unfancy_maybe_null template -auto _Unfancy_maybe_null(_Ptrty _Ptr) noexcept { // converts from a (potentially null) fancy pointer to a plain pointer +_CONSTEXPR20_CONTAINER auto _Unfancy_maybe_null(_Ptrty _Ptr) noexcept { + // converts from a (potentially null) fancy pointer to a plain pointer return _Ptr ? _STD addressof(*_Ptr) : nullptr; } template -_Ty* _Unfancy_maybe_null(_Ty* _Ptr) noexcept { // do nothing for plain pointers +_CONSTEXPR20_CONTAINER _Ty* _Unfancy_maybe_null(_Ty* _Ptr) noexcept { // do nothing for plain pointers return _Ptr; } @@ -445,17 +506,18 @@ public: using reverse_iterator = _STD reverse_iterator; using const_reverse_iterator = _STD reverse_iterator; - vector() noexcept(is_nothrow_default_constructible_v<_Alty>) : _Mypair(_Zero_then_variadic_args_t{}) { + _CONSTEXPR20_CONTAINER vector() noexcept(is_nothrow_default_constructible_v<_Alty>) + : _Mypair(_Zero_then_variadic_args_t{}) { _Mypair._Myval2._Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alty, _Getal())); } - explicit vector(const _Alloc& _Al) noexcept : _Mypair(_One_then_variadic_args_t{}, _Al) { + _CONSTEXPR20_CONTAINER explicit vector(const _Alloc& _Al) noexcept : _Mypair(_One_then_variadic_args_t{}, _Al) { _Mypair._Myval2._Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alty, _Getal())); } private: template - void _Construct_n_copies_of_ty(_CRT_GUARDOVERFLOW const size_type _Count, const _Ty2& _Val) { + _CONSTEXPR20_CONTAINER void _Construct_n_copies_of_ty(_CRT_GUARDOVERFLOW const size_type _Count, const _Ty2& _Val) { auto&& _Alproxy = _GET_PROXY_ALLOCATOR(_Alty, _Getal()); auto& _My_data = _Mypair._Myval2; _Container_proxy_ptr<_Alty> _Proxy(_Alproxy, _My_data); @@ -470,19 +532,20 @@ private: } public: - explicit vector(_CRT_GUARDOVERFLOW const size_type _Count, const _Alloc& _Al = _Alloc()) + _CONSTEXPR20_CONTAINER explicit vector(_CRT_GUARDOVERFLOW const size_type _Count, const _Alloc& _Al = _Alloc()) : _Mypair(_One_then_variadic_args_t{}, _Al) { _Construct_n_copies_of_ty(_Count, _Value_init_tag{}); } - vector(_CRT_GUARDOVERFLOW const size_type _Count, const _Ty& _Val, const _Alloc& _Al = _Alloc()) + _CONSTEXPR20_CONTAINER vector( + _CRT_GUARDOVERFLOW const size_type _Count, const _Ty& _Val, const _Alloc& _Al = _Alloc()) : _Mypair(_One_then_variadic_args_t{}, _Al) { _Construct_n_copies_of_ty(_Count, _Val); } private: template - void _Range_construct_or_tidy(_Iter _First, _Iter _Last, input_iterator_tag) { + _CONSTEXPR20_CONTAINER void _Range_construct_or_tidy(_Iter _First, _Iter _Last, input_iterator_tag) { _Tidy_guard _Guard{this}; for (; _First != _Last; ++_First) { emplace_back(*_First); // performance note: emplace_back()'s strong guarantee is unnecessary here @@ -492,7 +555,7 @@ private: } template - void _Range_construct_or_tidy(_Iter _First, _Iter _Last, forward_iterator_tag) { + _CONSTEXPR20_CONTAINER void _Range_construct_or_tidy(_Iter _First, _Iter _Last, forward_iterator_tag) { const auto _Count = _Convert_size(static_cast(_STD distance(_First, _Last))); if (_Count != 0) { _Buy_nonzero(_Count); @@ -505,7 +568,8 @@ private: public: template , int> = 0> - vector(_Iter _First, _Iter _Last, const _Alloc& _Al = _Alloc()) : _Mypair(_One_then_variadic_args_t{}, _Al) { + _CONSTEXPR20_CONTAINER vector(_Iter _First, _Iter _Last, const _Alloc& _Al = _Alloc()) + : _Mypair(_One_then_variadic_args_t{}, _Al) { auto&& _Alproxy = _GET_PROXY_ALLOCATOR(_Alty, _Getal()); _Container_proxy_ptr<_Alty> _Proxy(_Alproxy, _Mypair._Myval2); _Adl_verify_range(_First, _Last); @@ -513,14 +577,15 @@ public: _Proxy._Release(); } - vector(initializer_list<_Ty> _Ilist, const _Alloc& _Al = _Alloc()) : _Mypair(_One_then_variadic_args_t{}, _Al) { + _CONSTEXPR20_CONTAINER vector(initializer_list<_Ty> _Ilist, const _Alloc& _Al = _Alloc()) + : _Mypair(_One_then_variadic_args_t{}, _Al) { auto&& _Alproxy = _GET_PROXY_ALLOCATOR(_Alty, _Getal()); _Container_proxy_ptr<_Alty> _Proxy(_Alproxy, _Mypair._Myval2); _Range_construct_or_tidy(_Ilist.begin(), _Ilist.end(), random_access_iterator_tag{}); _Proxy._Release(); } - vector(const vector& _Right) + _CONSTEXPR20_CONTAINER vector(const vector& _Right) : _Mypair(_One_then_variadic_args_t{}, _Alty_traits::select_on_container_copy_construction(_Right._Getal())) { auto&& _Alproxy = _GET_PROXY_ALLOCATOR(_Alty, _Getal()); auto& _My_data = _Mypair._Myval2; @@ -538,7 +603,7 @@ public: _Proxy._Release(); } - vector(const vector& _Right, const _Alloc& _Al) : _Mypair(_One_then_variadic_args_t{}, _Al) { + _CONSTEXPR20_CONTAINER vector(const vector& _Right, const _Alloc& _Al) : _Mypair(_One_then_variadic_args_t{}, _Al) { auto&& _Alproxy = _GET_PROXY_ALLOCATOR(_Alty, _Getal()); auto& _My_data = _Mypair._Myval2; const auto& _Right_data = _Right._Mypair._Myval2; @@ -556,11 +621,13 @@ public: } private: - void _Move_construct(vector& _Right, true_type) noexcept { // move from _Right, stealing its contents + _CONSTEXPR20_CONTAINER void _Move_construct(vector& _Right, true_type) noexcept { + // move from _Right, stealing its contents _Mypair._Myval2._Take_contents(_Right._Mypair._Myval2); } - void _Move_construct(vector& _Right, false_type) { // move from _Right, possibly moving its contents + _CONSTEXPR20_CONTAINER void _Move_construct(vector& _Right, false_type) { + // move from _Right, possibly moving its contents if constexpr (!_Alty_traits::is_always_equal::value) { if (_Getal() != _Right._Getal()) { const auto& _Right_data = _Right._Mypair._Myval2; @@ -581,7 +648,7 @@ private: } public: - vector(vector&& _Right) noexcept + _CONSTEXPR20_CONTAINER vector(vector&& _Right) noexcept : _Mypair(_One_then_variadic_args_t{}, _STD move(_Right._Getal()), _STD exchange(_Right._Mypair._Myval2._Myfirst, nullptr), _STD exchange(_Right._Mypair._Myval2._Mylast, nullptr), @@ -590,7 +657,8 @@ public: _Mypair._Myval2._Swap_proxy_and_iterators(_Right._Mypair._Myval2); } - vector(vector&& _Right, const _Alloc& _Al) noexcept(_Alty_traits::is_always_equal::value) // strengthened + _CONSTEXPR20_CONTAINER vector(vector&& _Right, const _Alloc& _Al) noexcept( + _Alty_traits::is_always_equal::value) // strengthened : _Mypair(_One_then_variadic_args_t{}, _Al) { auto&& _Alproxy = _GET_PROXY_ALLOCATOR(_Alty, _Getal()); _Container_proxy_ptr<_Alty> _Proxy(_Alproxy, _Mypair._Myval2); @@ -599,13 +667,13 @@ public: } private: - void _Move_assign(vector& _Right, _Equal_allocators) noexcept { + _CONSTEXPR20_CONTAINER void _Move_assign(vector& _Right, _Equal_allocators) noexcept { _Tidy(); _Pocma(_Getal(), _Right._Getal()); _Mypair._Myval2._Take_contents(_Right._Mypair._Myval2); } - void _Move_assign(vector& _Right, _Propagate_allocators) noexcept /* terminates */ { + _CONSTEXPR20_CONTAINER void _Move_assign(vector& _Right, _Propagate_allocators) noexcept /* terminates */ { _Tidy(); #if _ITERATOR_DEBUG_LEVEL != 0 if (_Getal() != _Right._Getal()) { @@ -619,7 +687,7 @@ private: _Mypair._Myval2._Take_contents(_Right._Mypair._Myval2); } - void _Move_assign(vector& _Right, _No_propagate_allocators) { + _CONSTEXPR20_CONTAINER void _Move_assign(vector& _Right, _No_propagate_allocators) { if (_Getal() == _Right._Getal()) { _Move_assign(_Right, _Equal_allocators{}); } else { @@ -665,7 +733,8 @@ private: } public: - vector& operator=(vector&& _Right) noexcept(noexcept(_Move_assign(_Right, _Choose_pocma<_Alty>{}))) { + _CONSTEXPR20_CONTAINER vector& operator=(vector&& _Right) noexcept( + noexcept(_Move_assign(_Right, _Choose_pocma<_Alty>{}))) { if (this != _STD addressof(_Right)) { _Move_assign(_Right, _Choose_pocma<_Alty>{}); } @@ -673,7 +742,7 @@ public: return *this; } - ~vector() noexcept { + _CONSTEXPR20_CONTAINER ~vector() noexcept { _Tidy(); #if _ITERATOR_DEBUG_LEVEL != 0 auto&& _Alproxy = _GET_PROXY_ALLOCATOR(_Alty, _Getal()); @@ -683,7 +752,7 @@ public: private: template - decltype(auto) _Emplace_back_with_unused_capacity(_Valty&&... _Val) { + _CONSTEXPR20_CONTAINER decltype(auto) _Emplace_back_with_unused_capacity(_Valty&&... _Val) { // insert by perfectly forwarding into element at end, provide strong guarantee auto& _My_data = _Mypair._Myval2; pointer& _Mylast = _My_data._Mylast; @@ -701,7 +770,7 @@ private: public: template - decltype(auto) emplace_back(_Valty&&... _Val) { + _CONSTEXPR20_CONTAINER decltype(auto) emplace_back(_Valty&&... _Val) { // insert by perfectly forwarding into element at end, provide strong guarantee auto& _My_data = _Mypair._Myval2; pointer& _Mylast = _My_data._Mylast; @@ -717,16 +786,17 @@ public: #endif // _HAS_CXX17 } - void push_back(const _Ty& _Val) { // insert element at end, provide strong guarantee + _CONSTEXPR20_CONTAINER void push_back(const _Ty& _Val) { // insert element at end, provide strong guarantee emplace_back(_Val); } - void push_back(_Ty&& _Val) { // insert by moving into element at end, provide strong guarantee + _CONSTEXPR20_CONTAINER void push_back( + _Ty&& _Val) { // insert by moving into element at end, provide strong guarantee emplace_back(_STD move(_Val)); } template - pointer _Emplace_reallocate(const pointer _Whereptr, _Valty&&... _Val) { + _CONSTEXPR20_CONTAINER pointer _Emplace_reallocate(const pointer _Whereptr, _Valty&&... _Val) { // reallocate and insert by perfectly forwarding _Val at _Whereptr _Alty& _Al = _Getal(); auto& _My_data = _Mypair._Myval2; @@ -771,14 +841,20 @@ public: } template - iterator emplace(const_iterator _Where, _Valty&&... _Val) { // insert by perfectly forwarding _Val at _Where + _CONSTEXPR20_CONTAINER iterator emplace(const_iterator _Where, _Valty&&... _Val) { + // insert by perfectly forwarding _Val at _Where const pointer _Whereptr = _Where._Ptr; auto& _My_data = _Mypair._Myval2; const pointer _Oldlast = _My_data._Mylast; #if _ITERATOR_DEBUG_LEVEL == 2 - _STL_VERIFY( - _Where._Getcont() == _STD addressof(_My_data) && _Whereptr >= _My_data._Myfirst && _Oldlast >= _Whereptr, - "vector emplace iterator outside range"); +#ifdef __cpp_lib_constexpr_dynamic_alloc + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_constexpr_dynamic_alloc + { + _STL_VERIFY(_Where._Getcont() == _STD addressof(_My_data) && _Whereptr >= _My_data._Myfirst + && _Oldlast >= _Whereptr, + "vector emplace iterator outside range"); + } #endif // _ITERATOR_DEBUG_LEVEL == 2 if (_Oldlast != _My_data._Myend) { @@ -801,15 +877,16 @@ public: return _Make_iterator(_Emplace_reallocate(_Whereptr, _STD forward<_Valty>(_Val)...)); } - iterator insert(const_iterator _Where, const _Ty& _Val) { // insert _Val at _Where + _CONSTEXPR20_CONTAINER iterator insert(const_iterator _Where, const _Ty& _Val) { // insert _Val at _Where return emplace(_Where, _Val); } - iterator insert(const_iterator _Where, _Ty&& _Val) { // insert by moving _Val at _Where + _CONSTEXPR20_CONTAINER iterator insert(const_iterator _Where, _Ty&& _Val) { // insert by moving _Val at _Where return emplace(_Where, _STD move(_Val)); } - iterator insert(const_iterator _Where, _CRT_GUARDOVERFLOW const size_type _Count, const _Ty& _Val) { + _CONSTEXPR20_CONTAINER iterator insert( + const_iterator _Where, _CRT_GUARDOVERFLOW const size_type _Count, const _Ty& _Val) { // insert _Count * _Val at _Where const pointer _Whereptr = _Where._Ptr; @@ -819,8 +896,14 @@ public: const pointer _Oldfirst = _My_data._Myfirst; const pointer _Oldlast = _Mylast; #if _ITERATOR_DEBUG_LEVEL == 2 - _STL_VERIFY(_Where._Getcont() == _STD addressof(_My_data) && _Whereptr >= _Oldfirst && _Oldlast >= _Whereptr, - "vector insert iterator outside range"); +#ifdef __cpp_lib_constexpr_dynamic_alloc + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_constexpr_dynamic_alloc + { + _STL_VERIFY( + _Where._Getcont() == _STD addressof(_My_data) && _Whereptr >= _Oldfirst && _Oldlast >= _Whereptr, + "vector insert iterator outside range"); + } #endif // _ITERATOR_DEBUG_LEVEL == 2 const auto _Whereoff = static_cast(_Whereptr - _Oldfirst); @@ -883,7 +966,7 @@ public: private: template - void _Insert_range(const_iterator _Where, _Iter _First, _Iter _Last, input_iterator_tag) { + _CONSTEXPR20_CONTAINER void _Insert_range(const_iterator _Where, _Iter _First, _Iter _Last, input_iterator_tag) { // insert input range [_First, _Last) at _Where if (_First == _Last) { return; // nothing to do, avoid invalidating iterators @@ -909,7 +992,7 @@ private: } template - void _Insert_range(const_iterator _Where, _Iter _First, _Iter _Last, forward_iterator_tag) { + _CONSTEXPR20_CONTAINER void _Insert_range(const_iterator _Where, _Iter _First, _Iter _Last, forward_iterator_tag) { // insert forward range [_First, _Last) at _Where const pointer _Whereptr = _Where._Ptr; const auto _Count = _Convert_size(static_cast(_STD distance(_First, _Last))); @@ -1018,14 +1101,19 @@ private: public: template , int> = 0> - iterator insert(const_iterator _Where, _Iter _First, _Iter _Last) { + _CONSTEXPR20_CONTAINER iterator insert(const_iterator _Where, _Iter _First, _Iter _Last) { const pointer _Whereptr = _Where._Ptr; auto& _My_data = _Mypair._Myval2; const pointer _Oldfirst = _My_data._Myfirst; #if _ITERATOR_DEBUG_LEVEL == 2 - _STL_VERIFY( - _Where._Getcont() == _STD addressof(_My_data) && _Whereptr >= _Oldfirst && _My_data._Mylast >= _Whereptr, - "vector insert iterator outside range"); +#ifdef __cpp_lib_constexpr_dynamic_alloc + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_constexpr_dynamic_alloc + { + _STL_VERIFY(_Where._Getcont() == _STD addressof(_My_data) && _Whereptr >= _Oldfirst + && _My_data._Mylast >= _Whereptr, + "vector insert iterator outside range"); + } #endif // _ITERATOR_DEBUG_LEVEL == 2 _Adl_verify_range(_First, _Last); @@ -1034,11 +1122,12 @@ public: return _Make_iterator_offset(_Whereoff); } - iterator insert(const_iterator _Where, initializer_list<_Ty> _Ilist) { + _CONSTEXPR20_CONTAINER iterator insert(const_iterator _Where, initializer_list<_Ty> _Ilist) { return insert(_Where, _Ilist.begin(), _Ilist.end()); } - void assign(_CRT_GUARDOVERFLOW const size_type _Newsize, const _Ty& _Val) { // assign _Newsize * _Val + _CONSTEXPR20_CONTAINER void assign(_CRT_GUARDOVERFLOW const size_type _Newsize, const _Ty& _Val) { + // assign _Newsize * _Val auto& _My_data = _Mypair._Myval2; pointer& _Myfirst = _My_data._Myfirst; pointer& _Mylast = _My_data._Mylast; @@ -1066,7 +1155,8 @@ public: private: template - void _Assign_range(_Iter _First, _Iter _Last, input_iterator_tag) { // assign input range [_First, _Last) + _CONSTEXPR20_CONTAINER void _Assign_range(_Iter _First, _Iter _Last, input_iterator_tag) { + // assign input range [_First, _Last) auto& _My_data = _Mypair._Myval2; pointer& _Myfirst = _My_data._Myfirst; pointer& _Mylast = _My_data._Mylast; @@ -1095,7 +1185,8 @@ private: } template - void _Assign_range(_Iter _First, _Iter _Last, forward_iterator_tag) { // assign forward range [_First, _Last) + _CONSTEXPR20_CONTAINER void _Assign_range(_Iter _First, _Iter _Last, forward_iterator_tag) { + // assign forward range [_First, _Last) const auto _Newsize = _Convert_size(static_cast(_STD distance(_First, _Last))); auto& _My_data = _Mypair._Myval2; pointer& _Myfirst = _My_data._Myfirst; @@ -1107,54 +1198,59 @@ private: if constexpr (conjunction_v::_Trivially_copyable>, _Uses_default_construct<_Alty, _Ty*, decltype(*_First)>, _Uses_default_destroy<_Alty, _Ty*>>) { - const auto _Oldcapacity = static_cast(_Myend - _Myfirst); - if (_Newsize > _Oldcapacity) { - _Clear_and_reserve_geometric(_Newsize); - } - - _Mylast = _Refancy(_Copy_memmove(_First, _Last, _Unfancy(_Myfirst))); - } else { - auto _Oldsize = static_cast(_Mylast - _Myfirst); - - if (_Newsize > _Oldsize) { +#ifdef __cpp_lib_constexpr_dynamic_alloc + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_constexpr_dynamic_alloc + { const auto _Oldcapacity = static_cast(_Myend - _Myfirst); - if (_Newsize > _Oldcapacity) { // reallocate + if (_Newsize > _Oldcapacity) { _Clear_and_reserve_geometric(_Newsize); - _Oldsize = 0; } - // performance note: traversing [_First, _Mid) twice - const _Iter _Mid = _STD next(_First, static_cast(_Oldsize)); - _Copy_unchecked(_First, _Mid, _Myfirst); - _Mylast = _Ucopy(_Mid, _Last, _Mylast); - } else { - const pointer _Newlast = _Myfirst + _Newsize; - _Copy_unchecked(_First, _Last, _Myfirst); - _Destroy(_Newlast, _Mylast); - _Mylast = _Newlast; + _Mylast = _Refancy(_Copy_memmove(_First, _Last, _Unfancy(_Myfirst))); + return; } } + auto _Oldsize = static_cast(_Mylast - _Myfirst); + + if (_Newsize > _Oldsize) { + const auto _Oldcapacity = static_cast(_Myend - _Myfirst); + if (_Newsize > _Oldcapacity) { // reallocate + _Clear_and_reserve_geometric(_Newsize); + _Oldsize = 0; + } + + // performance note: traversing [_First, _Mid) twice + const _Iter _Mid = _STD next(_First, static_cast(_Oldsize)); + _Copy_unchecked(_First, _Mid, _Myfirst); + _Mylast = _Ucopy(_Mid, _Last, _Mylast); + } else { + const pointer _Newlast = _Myfirst + _Newsize; + _Copy_unchecked(_First, _Last, _Myfirst); + _Destroy(_Newlast, _Mylast); + _Mylast = _Newlast; + } } public: template , int> = 0> - void assign(_Iter _First, _Iter _Last) { + _CONSTEXPR20_CONTAINER void assign(_Iter _First, _Iter _Last) { _Adl_verify_range(_First, _Last); _Assign_range(_Get_unwrapped(_First), _Get_unwrapped(_Last), _Iter_cat_t<_Iter>{}); } - void assign(initializer_list<_Ty> _Ilist) { + _CONSTEXPR20_CONTAINER void assign(initializer_list<_Ty> _Ilist) { _Assign_range(_Ilist.begin(), _Ilist.end(), random_access_iterator_tag{}); } private: - void _Copy_assign(const vector& _Right, false_type) { + _CONSTEXPR20_CONTAINER void _Copy_assign(const vector& _Right, false_type) { _Pocca(_Getal(), _Right._Getal()); auto& _Right_data = _Right._Mypair._Myval2; assign(_Right_data._Myfirst, _Right_data._Mylast); } - void _Copy_assign(const vector& _Right, true_type) { + _CONSTEXPR20_CONTAINER void _Copy_assign(const vector& _Right, true_type) { if (_Getal() != _Right._Getal()) { _Tidy(); _Mypair._Myval2._Reload_proxy( @@ -1165,7 +1261,7 @@ private: } public: - vector& operator=(const vector& _Right) { + _CONSTEXPR20_CONTAINER vector& operator=(const vector& _Right) { if (this != _STD addressof(_Right)) { _Copy_assign(_Right, _Choose_pocca<_Alty>{}); } @@ -1173,14 +1269,14 @@ public: return *this; } - vector& operator=(initializer_list<_Ty> _Ilist) { + _CONSTEXPR20_CONTAINER vector& operator=(initializer_list<_Ty> _Ilist) { _Assign_range(_Ilist.begin(), _Ilist.end(), random_access_iterator_tag{}); return *this; } private: template - void _Resize_reallocate(const size_type _Newsize, const _Ty2& _Val) { + _CONSTEXPR20_CONTAINER void _Resize_reallocate(const size_type _Newsize, const _Ty2& _Val) { if (_Newsize > max_size()) { _Xlength(); } @@ -1209,7 +1305,8 @@ private: } template - void _Resize(const size_type _Newsize, const _Ty2& _Val) { // trim or append elements, provide strong guarantee + _CONSTEXPR20_CONTAINER void _Resize(const size_type _Newsize, const _Ty2& _Val) { + // trim or append elements, provide strong guarantee auto& _My_data = _Mypair._Myval2; pointer& _Myfirst = _My_data._Myfirst; pointer& _Mylast = _My_data._Mylast; @@ -1238,18 +1335,18 @@ private: } public: - void resize(_CRT_GUARDOVERFLOW const size_type _Newsize) { + _CONSTEXPR20_CONTAINER void resize(_CRT_GUARDOVERFLOW const size_type _Newsize) { // trim or append value-initialized elements, provide strong guarantee _Resize(_Newsize, _Value_init_tag{}); } - void resize(_CRT_GUARDOVERFLOW const size_type _Newsize, const _Ty& _Val) { + _CONSTEXPR20_CONTAINER void resize(_CRT_GUARDOVERFLOW const size_type _Newsize, const _Ty& _Val) { // trim or append copies of _Val, provide strong guarantee _Resize(_Newsize, _Val); } private: - void _Reallocate_exactly(const size_type _Newcapacity) { + _CONSTEXPR20_CONTAINER void _Reallocate_exactly(const size_type _Newcapacity) { // set capacity to _Newcapacity (without geometric growth), provide strong guarantee auto& _My_data = _Mypair._Myval2; pointer& _Myfirst = _My_data._Myfirst; @@ -1269,7 +1366,24 @@ private: _Change_array(_Newvec, _Size, _Newcapacity); } - void _Clear_and_reserve_geometric(const size_type _Newsize) { +#if _ITERATOR_DEBUG_LEVEL != 0 + void _Check_all_orphaned_locked() const noexcept { + _Lockit _Lock(_LOCK_DEBUG); + auto& _My_data = _Mypair._Myval2; + _STL_INTERNAL_CHECK(!_My_data._Myproxy->_Myfirstiter); + } + + _CONSTEXPR20_CONTAINER void _Check_all_orphaned() const noexcept { +#ifdef __cpp_lib_constexpr_dynamic_alloc + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_constexpr_dynamic_alloc + { + _Check_all_orphaned_locked(); + } + } +#endif // _ITERATOR_DEBUG_LEVEL != 0 + + _CONSTEXPR20_CONTAINER void _Clear_and_reserve_geometric(const size_type _Newsize) { auto& _My_data = _Mypair._Myval2; pointer& _Myfirst = _My_data._Myfirst; pointer& _Mylast = _My_data._Mylast; @@ -1277,10 +1391,7 @@ private: #if _ITERATOR_DEBUG_LEVEL != 0 && defined(_ENABLE_STL_INTERNAL_CHECK) _STL_INTERNAL_CHECK(_Newsize != 0); - { - _Lockit _Lock(_LOCK_DEBUG); - _STL_INTERNAL_CHECK(!_My_data._Myproxy->_Myfirstiter); // asserts that all iterators are orphaned - } // unlock + _Check_all_orphaned(); #endif // _ITERATOR_DEBUG_LEVEL != 0 && defined(_ENABLE_STL_INTERNAL_CHECK) if (_Newsize > max_size()) { @@ -1302,7 +1413,7 @@ private: } public: - void reserve(_CRT_GUARDOVERFLOW const size_type _Newcapacity) { + _CONSTEXPR20_CONTAINER void reserve(_CRT_GUARDOVERFLOW const size_type _Newcapacity) { // increase capacity to _Newcapacity (without geometric growth), provide strong guarantee if (_Newcapacity > capacity()) { // something to do (reserve() never shrinks) if (_Newcapacity > max_size()) { @@ -1313,7 +1424,7 @@ public: } } - void shrink_to_fit() { // reduce capacity to size, provide strong guarantee + _CONSTEXPR20_CONTAINER void shrink_to_fit() { // reduce capacity to size, provide strong guarantee auto& _My_data = _Mypair._Myval2; const pointer _Oldlast = _My_data._Mylast; if (_Oldlast != _My_data._Myend) { // something to do @@ -1326,29 +1437,40 @@ public: } } - void pop_back() noexcept /* strengthened */ { + _CONSTEXPR20_CONTAINER void pop_back() noexcept /* strengthened */ { auto& _My_data = _Mypair._Myval2; pointer& _Mylast = _My_data._Mylast; #if _ITERATOR_DEBUG_LEVEL == 2 - _STL_VERIFY(_My_data._Myfirst != _Mylast, "vector empty before pop"); - _Orphan_range(_Mylast - 1, _Mylast); +#ifdef __cpp_lib_constexpr_dynamic_alloc + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_constexpr_dynamic_alloc + { + _STL_VERIFY(_My_data._Myfirst != _Mylast, "vector empty before pop"); + _Orphan_range(_Mylast - 1, _Mylast); + } #endif // _ITERATOR_DEBUG_LEVEL == 2 _Alty_traits::destroy(_Getal(), _Unfancy(_Mylast - 1)); --_Mylast; } - iterator erase(const_iterator _Where) noexcept(is_nothrow_move_assignable_v) /* strengthened */ { + _CONSTEXPR20_CONTAINER iterator erase(const_iterator _Where) noexcept( + is_nothrow_move_assignable_v) /* strengthened */ { const pointer _Whereptr = _Where._Ptr; auto& _My_data = _Mypair._Myval2; pointer& _Mylast = _My_data._Mylast; #if _ITERATOR_DEBUG_LEVEL == 2 - _STL_VERIFY( - _Where._Getcont() == _STD addressof(_My_data) && _Whereptr >= _My_data._Myfirst && _Mylast > _Whereptr, - "vector erase iterator outside range"); - _Orphan_range(_Whereptr, _Mylast); +#ifdef __cpp_lib_constexpr_dynamic_alloc + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_constexpr_dynamic_alloc + { + _STL_VERIFY( + _Where._Getcont() == _STD addressof(_My_data) && _Whereptr >= _My_data._Myfirst && _Mylast > _Whereptr, + "vector erase iterator outside range"); + _Orphan_range(_Whereptr, _Mylast); + } #endif // _ITERATOR_DEBUG_LEVEL == 2 _Move_unchecked(_Whereptr + 1, _Mylast, _Whereptr); @@ -1357,7 +1479,7 @@ public: return iterator(_Whereptr, _STD addressof(_My_data)); } - iterator erase(const_iterator _First, const_iterator _Last) noexcept( + _CONSTEXPR20_CONTAINER iterator erase(const_iterator _First, const_iterator _Last) noexcept( is_nothrow_move_assignable_v) /* strengthened */ { const pointer _Firstptr = _First._Ptr; const pointer _Lastptr = _Last._Ptr; @@ -1365,9 +1487,14 @@ public: pointer& _Mylast = _My_data._Mylast; #if _ITERATOR_DEBUG_LEVEL == 2 - _STL_VERIFY(_First._Getcont() == _STD addressof(_My_data) && _Last._Getcont() == _STD addressof(_My_data) - && _Firstptr >= _My_data._Myfirst && _Lastptr >= _Firstptr && _Mylast >= _Lastptr, - "vector erase iterator outside range"); +#ifdef __cpp_lib_constexpr_dynamic_alloc + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_constexpr_dynamic_alloc + { + _STL_VERIFY(_First._Getcont() == _STD addressof(_My_data) && _Last._Getcont() == _STD addressof(_My_data) + && _Firstptr >= _My_data._Myfirst && _Lastptr >= _Firstptr && _Mylast >= _Lastptr, + "vector erase iterator outside range"); + } #endif // _ITERATOR_DEBUG_LEVEL == 2 if (_Firstptr != _Lastptr) { // something to do, invalidate iterators @@ -1381,7 +1508,7 @@ public: return iterator(_Firstptr, _STD addressof(_My_data)); } - void clear() noexcept { // erase all + _CONSTEXPR20_CONTAINER void clear() noexcept { // erase all auto& _My_data = _Mypair._Myval2; pointer& _Myfirst = _My_data._Myfirst; pointer& _Mylast = _My_data._Mylast; @@ -1392,130 +1519,140 @@ public: } public: - void swap(vector& _Right) noexcept /* strengthened */ { + _CONSTEXPR20_CONTAINER void swap(vector& _Right) noexcept /* strengthened */ { if (this != _STD addressof(_Right)) { _Pocs(_Getal(), _Right._Getal()); _Mypair._Myval2._Swap_val(_Right._Mypair._Myval2); } } - _NODISCARD _Ty* data() noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER _Ty* data() noexcept { return _Unfancy_maybe_null(_Mypair._Myval2._Myfirst); } - _NODISCARD const _Ty* data() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER const _Ty* data() const noexcept { return _Unfancy_maybe_null(_Mypair._Myval2._Myfirst); } - _NODISCARD iterator begin() noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER iterator begin() noexcept { auto& _My_data = _Mypair._Myval2; return iterator(_My_data._Myfirst, _STD addressof(_My_data)); } - _NODISCARD const_iterator begin() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER const_iterator begin() const noexcept { auto& _My_data = _Mypair._Myval2; return const_iterator(_My_data._Myfirst, _STD addressof(_My_data)); } - _NODISCARD iterator end() noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER iterator end() noexcept { auto& _My_data = _Mypair._Myval2; return iterator(_My_data._Mylast, _STD addressof(_My_data)); } - _NODISCARD const_iterator end() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER const_iterator end() const noexcept { auto& _My_data = _Mypair._Myval2; return const_iterator(_My_data._Mylast, _STD addressof(_My_data)); } - _NODISCARD reverse_iterator rbegin() noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER reverse_iterator rbegin() noexcept { return reverse_iterator(end()); } - _NODISCARD const_reverse_iterator rbegin() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); } - _NODISCARD reverse_iterator rend() noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER reverse_iterator rend() noexcept { return reverse_iterator(begin()); } - _NODISCARD const_reverse_iterator rend() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); } - _NODISCARD const_iterator cbegin() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER const_iterator cbegin() const noexcept { return begin(); } - _NODISCARD const_iterator cend() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER const_iterator cend() const noexcept { return end(); } - _NODISCARD const_reverse_iterator crbegin() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER const_reverse_iterator crbegin() const noexcept { return rbegin(); } - _NODISCARD const_reverse_iterator crend() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER const_reverse_iterator crend() const noexcept { return rend(); } - pointer _Unchecked_begin() noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER pointer _Unchecked_begin() noexcept { return _Mypair._Myval2._Myfirst; } - const_pointer _Unchecked_begin() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER const_pointer _Unchecked_begin() const noexcept { return _Mypair._Myval2._Myfirst; } - pointer _Unchecked_end() noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER pointer _Unchecked_end() noexcept { return _Mypair._Myval2._Mylast; } - const_pointer _Unchecked_end() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER const_pointer _Unchecked_end() const noexcept { return _Mypair._Myval2._Mylast; } - _NODISCARD bool empty() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER bool empty() const noexcept { auto& _My_data = _Mypair._Myval2; return _My_data._Myfirst == _My_data._Mylast; } - _NODISCARD size_type size() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER size_type size() const noexcept { auto& _My_data = _Mypair._Myval2; return static_cast(_My_data._Mylast - _My_data._Myfirst); } - _NODISCARD size_type max_size() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER size_type max_size() const noexcept { return (_STD min)( static_cast((numeric_limits::max)()), _Alty_traits::max_size(_Getal())); } - _NODISCARD size_type capacity() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER size_type capacity() const noexcept { auto& _My_data = _Mypair._Myval2; return static_cast(_My_data._Myend - _My_data._Myfirst); } - _NODISCARD _Ty& operator[](const size_type _Pos) noexcept /* strengthened */ { + _NODISCARD _CONSTEXPR20_CONTAINER _Ty& operator[](const size_type _Pos) noexcept /* strengthened */ { auto& _My_data = _Mypair._Myval2; #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY( - _Pos < static_cast(_My_data._Mylast - _My_data._Myfirst), "vector subscript out of range"); +#ifdef __cpp_lib_constexpr_dynamic_alloc + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_constexpr_dynamic_alloc + { + _STL_VERIFY( + _Pos < static_cast(_My_data._Mylast - _My_data._Myfirst), "vector subscript out of range"); + } #endif // _CONTAINER_DEBUG_LEVEL > 0 return _My_data._Myfirst[_Pos]; } - _NODISCARD const _Ty& operator[](const size_type _Pos) const noexcept /* strengthened */ { + _NODISCARD _CONSTEXPR20_CONTAINER const _Ty& operator[](const size_type _Pos) const noexcept /* strengthened */ { auto& _My_data = _Mypair._Myval2; #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY( - _Pos < static_cast(_My_data._Mylast - _My_data._Myfirst), "vector subscript out of range"); +#ifdef __cpp_lib_constexpr_dynamic_alloc + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_constexpr_dynamic_alloc + { + _STL_VERIFY( + _Pos < static_cast(_My_data._Mylast - _My_data._Myfirst), "vector subscript out of range"); + } #endif // _CONTAINER_DEBUG_LEVEL > 0 return _My_data._Myfirst[_Pos]; } - _NODISCARD _Ty& at(const size_type _Pos) { + _NODISCARD _CONSTEXPR20_CONTAINER _Ty& at(const size_type _Pos) { auto& _My_data = _Mypair._Myval2; if (static_cast(_My_data._Mylast - _My_data._Myfirst) <= _Pos) { _Xrange(); @@ -1524,7 +1661,7 @@ public: return _My_data._Myfirst[_Pos]; } - _NODISCARD const _Ty& at(const size_type _Pos) const { + _NODISCARD _CONSTEXPR20_CONTAINER const _Ty& at(const size_type _Pos) const { auto& _My_data = _Mypair._Myval2; if (static_cast(_My_data._Mylast - _My_data._Myfirst) <= _Pos) { _Xrange(); @@ -1533,87 +1670,109 @@ public: return _My_data._Myfirst[_Pos]; } - _NODISCARD _Ty& front() noexcept /* strengthened */ { + _NODISCARD _CONSTEXPR20_CONTAINER _Ty& front() noexcept /* strengthened */ { auto& _My_data = _Mypair._Myval2; #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(_My_data._Myfirst != _My_data._Mylast, "front() called on empty vector"); +#ifdef __cpp_lib_constexpr_dynamic_alloc + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_constexpr_dynamic_alloc + { + _STL_VERIFY(_My_data._Myfirst != _My_data._Mylast, "front() called on empty vector"); + } #endif // _CONTAINER_DEBUG_LEVEL > 0 return *_My_data._Myfirst; } - _NODISCARD const _Ty& front() const noexcept /* strengthened */ { + _NODISCARD _CONSTEXPR20_CONTAINER const _Ty& front() const noexcept /* strengthened */ { auto& _My_data = _Mypair._Myval2; #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(_My_data._Myfirst != _My_data._Mylast, "front() called on empty vector"); +#ifdef __cpp_lib_constexpr_dynamic_alloc + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_constexpr_dynamic_alloc + { + _STL_VERIFY(_My_data._Myfirst != _My_data._Mylast, "front() called on empty vector"); + } #endif // _CONTAINER_DEBUG_LEVEL > 0 return *_My_data._Myfirst; } - _NODISCARD _Ty& back() noexcept /* strengthened */ { + _NODISCARD _CONSTEXPR20_CONTAINER _Ty& back() noexcept /* strengthened */ { auto& _My_data = _Mypair._Myval2; #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(_My_data._Myfirst != _My_data._Mylast, "back() called on empty vector"); +#ifdef __cpp_lib_constexpr_dynamic_alloc + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_constexpr_dynamic_alloc + { + _STL_VERIFY(_My_data._Myfirst != _My_data._Mylast, "back() called on empty vector"); + } #endif // _CONTAINER_DEBUG_LEVEL > 0 return _My_data._Mylast[-1]; } - _NODISCARD const _Ty& back() const noexcept /* strengthened */ { + _NODISCARD _CONSTEXPR20_CONTAINER const _Ty& back() const noexcept /* strengthened */ { auto& _My_data = _Mypair._Myval2; #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(_My_data._Myfirst != _My_data._Mylast, "back() called on empty vector"); +#ifdef __cpp_lib_constexpr_dynamic_alloc + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_constexpr_dynamic_alloc + { + _STL_VERIFY(_My_data._Myfirst != _My_data._Mylast, "back() called on empty vector"); + } #endif // _CONTAINER_DEBUG_LEVEL > 0 return _My_data._Mylast[-1]; } - _NODISCARD allocator_type get_allocator() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER allocator_type get_allocator() const noexcept { return static_cast(_Getal()); } private: - pointer _Ufill(pointer _Dest, const size_type _Count, const _Ty& _Val) { + _CONSTEXPR20_CONTAINER pointer _Ufill(pointer _Dest, const size_type _Count, const _Ty& _Val) { // fill raw _Dest with _Count copies of _Val, using allocator return _Uninitialized_fill_n(_Dest, _Count, _Val, _Getal()); } - pointer _Ufill(pointer _Dest, const size_type _Count, _Value_init_tag) { + _CONSTEXPR20_CONTAINER pointer _Ufill(pointer _Dest, const size_type _Count, _Value_init_tag) { // fill raw _Dest with _Count value-initialized objects, using allocator return _Uninitialized_value_construct_n(_Dest, _Count, _Getal()); } template - pointer _Ucopy(_Iter _First, _Iter _Last, pointer _Dest) { // copy [_First, _Last) to raw _Dest, using allocator + _CONSTEXPR20_CONTAINER pointer _Ucopy(_Iter _First, _Iter _Last, pointer _Dest) { + // copy [_First, _Last) to raw _Dest, using allocator return _Uninitialized_copy(_First, _Last, _Dest, _Getal()); } - pointer _Umove(pointer _First, pointer _Last, pointer _Dest) { // move [_First, _Last) to raw _Dest, using allocator + _CONSTEXPR20_CONTAINER pointer _Umove(pointer _First, pointer _Last, pointer _Dest) { + // move [_First, _Last) to raw _Dest, using allocator return _Uninitialized_move(_First, _Last, _Dest, _Getal()); } - void _Umove_if_noexcept1(pointer _First, pointer _Last, pointer _Dest, true_type) { + _CONSTEXPR20_CONTAINER void _Umove_if_noexcept1(pointer _First, pointer _Last, pointer _Dest, true_type) { // move [_First, _Last) to raw _Dest, using allocator _Uninitialized_move(_First, _Last, _Dest, _Getal()); } - void _Umove_if_noexcept1(pointer _First, pointer _Last, pointer _Dest, false_type) { + _CONSTEXPR20_CONTAINER void _Umove_if_noexcept1(pointer _First, pointer _Last, pointer _Dest, false_type) { // copy [_First, _Last) to raw _Dest, using allocator _Uninitialized_copy(_First, _Last, _Dest, _Getal()); } - void _Umove_if_noexcept(pointer _First, pointer _Last, pointer _Dest) { + _CONSTEXPR20_CONTAINER void _Umove_if_noexcept(pointer _First, pointer _Last, pointer _Dest) { // move_if_noexcept [_First, _Last) to raw _Dest, using allocator _Umove_if_noexcept1(_First, _Last, _Dest, bool_constant, negation>>>{}); } - void _Destroy(pointer _First, pointer _Last) { // destroy [_First, _Last) using allocator + _CONSTEXPR20_CONTAINER void _Destroy(pointer _First, pointer _Last) { // destroy [_First, _Last) using allocator _Destroy_range(_First, _Last, _Getal()); } - size_type _Calculate_growth(const size_type _Newsize) const { + _CONSTEXPR20_CONTAINER size_type _Calculate_growth(const size_type _Newsize) const { // given _Oldcapacity and _Newsize, calculate geometric growth const size_type _Oldcapacity = capacity(); const auto _Max = max_size(); @@ -1631,7 +1790,7 @@ private: return _Geometric; // geometric growth is sufficient } - void _Buy_raw(const size_type _Newcapacity) { + _CONSTEXPR20_CONTAINER void _Buy_raw(const size_type _Newcapacity) { // allocate array with _Newcapacity elements auto& _My_data = _Mypair._Myval2; pointer& _Myfirst = _My_data._Myfirst; @@ -1647,7 +1806,7 @@ private: _Myend = _Newvec + _Newcapacity; } - void _Buy_nonzero(const size_type _Newcapacity) { + _CONSTEXPR20_CONTAINER void _Buy_nonzero(const size_type _Newcapacity) { // allocate array with _Newcapacity elements #ifdef _ENABLE_STL_INTERNAL_CHECK auto& _My_data = _Mypair._Myval2; @@ -1665,7 +1824,8 @@ private: _Buy_raw(_Newcapacity); } - void _Change_array(const pointer _Newvec, const size_type _Newsize, const size_type _Newcapacity) { + _CONSTEXPR20_CONTAINER void _Change_array( + const pointer _Newvec, const size_type _Newsize, const size_type _Newcapacity) { // orphan all iterators, discard old array, acquire new array auto& _My_data = _Mypair._Myval2; pointer& _Myfirst = _My_data._Myfirst; @@ -1684,7 +1844,7 @@ private: _Myend = _Newvec + _Newcapacity; } - void _Tidy() noexcept { // free all storage + _CONSTEXPR20_CONTAINER void _Tidy() noexcept { // free all storage auto& _My_data = _Mypair._Myval2; pointer& _Myfirst = _My_data._Myfirst; pointer& _Mylast = _My_data._Mylast; @@ -1710,10 +1870,9 @@ private: _Xout_of_range("invalid vector subscript"); } - void _Orphan_range(pointer _First, pointer _Last) const { // orphan iterators within specified (inclusive) range #if _ITERATOR_DEBUG_LEVEL == 2 + void _Orphan_range_locked(pointer _First, pointer _Last) const { _Lockit _Lock(_LOCK_DEBUG); - _Iterator_base12** _Pnext = &_Mypair._Myval2._Myproxy->_Myfirstiter; while (*_Pnext) { const auto _Pnextptr = static_cast(**_Pnext)._Ptr; @@ -1724,25 +1883,33 @@ private: *_Pnext = (*_Pnext)->_Mynextiter; } } -#else // ^^^ _ITERATOR_DEBUG_LEVEL == 2 ^^^ // vvv _ITERATOR_DEBUG_LEVEL != 2 vvv - (void) _First; - (void) _Last; -#endif // _ITERATOR_DEBUG_LEVEL == 2 } - _Alty& _Getal() noexcept { + _CONSTEXPR20_CONTAINER void _Orphan_range(pointer _First, pointer _Last) const { +#ifdef __cpp_lib_constexpr_dynamic_alloc + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_constexpr_dynamic_alloc + { + _Orphan_range_locked(_First, _Last); + } + } +#else // ^^^ _ITERATOR_DEBUG_LEVEL == 2 ^^^ // vvv _ITERATOR_DEBUG_LEVEL != 2 vvv + _CONSTEXPR20_CONTAINER void _Orphan_range(pointer, pointer) const {} +#endif // _ITERATOR_DEBUG_LEVEL != 2 + + _NODISCARD _CONSTEXPR20_CONTAINER _Alty& _Getal() noexcept { return _Mypair._Get_first(); } - const _Alty& _Getal() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER const _Alty& _Getal() const noexcept { return _Mypair._Get_first(); } - iterator _Make_iterator(const pointer _Ptr) noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER iterator _Make_iterator(const pointer _Ptr) noexcept { return iterator(_Ptr, _STD addressof(_Mypair._Myval2)); } - iterator _Make_iterator_offset(const size_type _Offset) noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER iterator _Make_iterator_offset(const size_type _Offset) noexcept { // return the iterator begin() + _Offset without a debugging check auto& _My_data = _Mypair._Myval2; return iterator(_My_data._Myfirst + _Offset, _STD addressof(_My_data)); @@ -1758,39 +1925,39 @@ vector(_Iter, _Iter, _Alloc = _Alloc()) -> vector<_Iter_value_t<_Iter>, _Alloc>; #endif // _HAS_CXX17 template -void swap(vector<_Ty, _Alloc>& _Left, vector<_Ty, _Alloc>& _Right) noexcept /* strengthened */ { +_CONSTEXPR20_CONTAINER void swap(vector<_Ty, _Alloc>& _Left, vector<_Ty, _Alloc>& _Right) noexcept /* strengthened */ { _Left.swap(_Right); } template -_NODISCARD bool operator==(const vector<_Ty, _Alloc>& _Left, const vector<_Ty, _Alloc>& _Right) { +_NODISCARD _CONSTEXPR20_CONTAINER bool operator==(const vector<_Ty, _Alloc>& _Left, const vector<_Ty, _Alloc>& _Right) { return _Left.size() == _Right.size() && _STD equal(_Left._Unchecked_begin(), _Left._Unchecked_end(), _Right._Unchecked_begin()); } template -_NODISCARD bool operator!=(const vector<_Ty, _Alloc>& _Left, const vector<_Ty, _Alloc>& _Right) { +_NODISCARD _CONSTEXPR20_CONTAINER bool operator!=(const vector<_Ty, _Alloc>& _Left, const vector<_Ty, _Alloc>& _Right) { return !(_Left == _Right); } template -_NODISCARD bool operator<(const vector<_Ty, _Alloc>& _Left, const vector<_Ty, _Alloc>& _Right) { +_NODISCARD _CONSTEXPR20_CONTAINER bool operator<(const vector<_Ty, _Alloc>& _Left, const vector<_Ty, _Alloc>& _Right) { return _STD lexicographical_compare( _Left._Unchecked_begin(), _Left._Unchecked_end(), _Right._Unchecked_begin(), _Right._Unchecked_end()); } template -_NODISCARD bool operator>(const vector<_Ty, _Alloc>& _Left, const vector<_Ty, _Alloc>& _Right) { +_NODISCARD _CONSTEXPR20_CONTAINER bool operator>(const vector<_Ty, _Alloc>& _Left, const vector<_Ty, _Alloc>& _Right) { return _Right < _Left; } template -_NODISCARD bool operator<=(const vector<_Ty, _Alloc>& _Left, const vector<_Ty, _Alloc>& _Right) { +_NODISCARD _CONSTEXPR20_CONTAINER bool operator<=(const vector<_Ty, _Alloc>& _Left, const vector<_Ty, _Alloc>& _Right) { return !(_Right < _Left); } template -_NODISCARD bool operator>=(const vector<_Ty, _Alloc>& _Left, const vector<_Ty, _Alloc>& _Right) { +_NODISCARD _CONSTEXPR20_CONTAINER bool operator>=(const vector<_Ty, _Alloc>& _Left, const vector<_Ty, _Alloc>& _Right) { return !(_Left < _Right); } @@ -1813,21 +1980,21 @@ public: using _Difference_type = typename allocator_traits<_Alvbase>::difference_type; using _Mycont = vector>; - _Vb_iter_base() = default; + _CONSTEXPR20_CONTAINER _Vb_iter_base() = default; - _Vb_iter_base(const _Vbase* _Ptr, _Size_type _Off, const _Container_base* _Mypvbool) noexcept + _CONSTEXPR20_CONTAINER _Vb_iter_base(const _Vbase* _Ptr, _Size_type _Off, const _Container_base* _Mypvbool) noexcept : _Myptr(_Ptr), _Myoff(_Off) { this->_Adopt(_Mypvbool); } - void _Advance(_Size_type _Off) noexcept { + _CONSTEXPR20_CONTAINER void _Advance(_Size_type _Off) noexcept { _Myoff += _Off; _Myptr += _Myoff / _VBITS; _Myoff %= _VBITS; } #if _ITERATOR_DEBUG_LEVEL != 0 - _Difference_type _Total_off(const _Mycont* _Cont) const noexcept { + _CONSTEXPR20_CONTAINER _Difference_type _Total_off(const _Mycont* _Cont) const noexcept { return static_cast<_Difference_type>(_VBITS * (_Myptr - _Cont->_Myvec.data()) + _Myoff); } #endif // _ITERATOR_DEBUG_LEVEL != 0 @@ -1845,18 +2012,19 @@ class _Vb_reference : public _Vb_iter_base<_Alvbase_wrapped> { using _Difference_type = typename _Mybase::_Difference_type; // TRANSITION, ABI: non-trivial constructor - _Vb_reference() = default; + _CONSTEXPR20_CONTAINER _Vb_reference() = default; public: - _Vb_reference(const _Vb_reference&) = default; + _CONSTEXPR20_CONTAINER _Vb_reference(const _Vb_reference&) = default; - _Vb_reference(const _Mybase& _Right) noexcept : _Mybase(_Right._Myptr, _Right._Myoff, _Right._Getcont()) {} + _CONSTEXPR20_CONTAINER _Vb_reference(const _Mybase& _Right) noexcept + : _Mybase(_Right._Myptr, _Right._Myoff, _Right._Getcont()) {} - _Vb_reference& operator=(const _Vb_reference& _Right) noexcept { + _CONSTEXPR20_CONTAINER _Vb_reference& operator=(const _Vb_reference& _Right) noexcept { return *this = static_cast(_Right); } - _Vb_reference& operator=(bool _Val) noexcept { + _CONSTEXPR20_CONTAINER _Vb_reference& operator=(bool _Val) noexcept { if (_Val) { *const_cast<_Vbase*>(_Getptr()) |= _Mask(); } else { @@ -1866,33 +2034,38 @@ public: return *this; } - void flip() noexcept { + _CONSTEXPR20_CONTAINER void flip() noexcept { *const_cast<_Vbase*>(_Getptr()) ^= _Mask(); } - operator bool() const noexcept { + _CONSTEXPR20_CONTAINER operator bool() const noexcept { return (*_Getptr() & _Mask()) != 0; } - const _Vbase* _Getptr() const noexcept { + _CONSTEXPR20_CONTAINER const _Vbase* _Getptr() const noexcept { #if _ITERATOR_DEBUG_LEVEL != 0 - const auto _Cont = static_cast(this->_Getcont()); - _STL_VERIFY(_Cont, "cannot dereference value-initialized vector iterator"); - _STL_VERIFY(this->_Total_off(_Cont) <= static_cast<_Difference_type>(_Cont->_Mysize), - "vector iterator not dereferenceable"); +#ifdef __cpp_lib_constexpr_dynamic_alloc + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_constexpr_dynamic_alloc + { + const auto _Cont = static_cast(this->_Getcont()); + _STL_VERIFY(_Cont, "cannot dereference value-initialized vector iterator"); + _STL_VERIFY(this->_Total_off(_Cont) <= static_cast<_Difference_type>(_Cont->_Mysize), + "vector iterator not dereferenceable"); + } #endif // _ITERATOR_DEBUG_LEVEL != 0 return this->_Myptr; } - friend void swap(_Vb_reference _Left, _Vb_reference _Right) noexcept { + friend _CONSTEXPR20_CONTAINER void swap(_Vb_reference _Left, _Vb_reference _Right) noexcept { bool _Val = _Left; // NOT _STD swap _Left = _Right; _Right = _Val; } protected: - _Vbase _Mask() const noexcept { + _CONSTEXPR20_CONTAINER _Vbase _Mask() const noexcept { return static_cast<_Vbase>(1) << this->_Myoff; } }; @@ -1916,142 +2089,165 @@ public: using pointer = const_reference*; using reference = const_reference; - _Vb_const_iterator() = default; + _CONSTEXPR20_CONTAINER _Vb_const_iterator() = default; - _Vb_const_iterator(const _Vbase* _Ptr, const _Container_base* _Mypvbool) noexcept : _Mybase(_Ptr, 0, _Mypvbool) {} + _CONSTEXPR20_CONTAINER _Vb_const_iterator(const _Vbase* _Ptr, const _Container_base* _Mypvbool) noexcept + : _Mybase(_Ptr, 0, _Mypvbool) {} - _NODISCARD const_reference operator*() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER const_reference operator*() const noexcept { #if _ITERATOR_DEBUG_LEVEL != 0 - const auto _Cont = static_cast(this->_Getcont()); - _STL_VERIFY(_Cont, "cannot dereference value-initialized vector iterator"); - _STL_VERIFY(this->_Total_off(_Cont) < static_cast<_Difference_type>(_Cont->_Mysize), - "vector iterator not dereferenceable"); +#ifdef __cpp_lib_constexpr_dynamic_alloc + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_constexpr_dynamic_alloc + { + const auto _Cont = static_cast(this->_Getcont()); + _STL_VERIFY(_Cont, "cannot dereference value-initialized vector iterator"); + _STL_VERIFY(this->_Total_off(_Cont) < static_cast<_Difference_type>(_Cont->_Mysize), + "vector iterator not dereferenceable"); + } #endif // _ITERATOR_DEBUG_LEVEL != 0 return _Reft(*this); } - _Vb_const_iterator& operator++() noexcept { + _CONSTEXPR20_CONTAINER _Vb_const_iterator& operator++() noexcept { _Inc(); return *this; } - _Vb_const_iterator operator++(int) noexcept { + _CONSTEXPR20_CONTAINER _Vb_const_iterator operator++(int) noexcept { _Vb_const_iterator _Tmp = *this; _Inc(); return _Tmp; } - _Vb_const_iterator& operator--() noexcept { + _CONSTEXPR20_CONTAINER _Vb_const_iterator& operator--() noexcept { _Dec(); return *this; } - _Vb_const_iterator operator--(int) noexcept { + _CONSTEXPR20_CONTAINER _Vb_const_iterator operator--(int) noexcept { _Vb_const_iterator _Tmp = *this; _Dec(); return _Tmp; } - _Vb_const_iterator& operator+=(const difference_type _Off) noexcept { + _CONSTEXPR20_CONTAINER _Vb_const_iterator& operator+=(const difference_type _Off) noexcept { #if _ITERATOR_DEBUG_LEVEL != 0 - if (_Off != 0) { - const auto _Cont = static_cast(this->_Getcont()); - _STL_VERIFY(_Cont, "cannot seek value-initialized vector iterator"); - const auto _Start_offset = this->_Total_off(_Cont); - if (_Off < 0) { - _STL_VERIFY(-_Start_offset <= _Off, "cannot seek vector iterator before begin"); - } else if (0 < _Off) { - _STL_VERIFY(_Off <= static_cast<_Difference_type>(_Cont->_Mysize - _Start_offset), - "cannot seek vector iterator after end"); +#ifdef __cpp_lib_constexpr_dynamic_alloc + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_constexpr_dynamic_alloc + { + if (_Off != 0) { + const auto _Cont = static_cast(this->_Getcont()); + _STL_VERIFY(_Cont, "cannot seek value-initialized vector iterator"); + const auto _Start_offset = this->_Total_off(_Cont); + if (_Off < 0) { + _STL_VERIFY(-_Start_offset <= _Off, "cannot seek vector iterator before begin"); + } else if (0 < _Off) { + _STL_VERIFY(_Off <= static_cast<_Difference_type>(_Cont->_Mysize - _Start_offset), + "cannot seek vector iterator after end"); + } } } #endif // _ITERATOR_DEBUG_LEVEL != 0 if (_Off < 0 && this->_Myoff < 0 - static_cast<_Size_type>(_Off)) { // add negative increment - this->_Myoff += _Off; + this->_Myoff += static_cast<_Size_type>(_Off); this->_Myptr -= 1 + (static_cast<_Size_type>(-1) - this->_Myoff) / _VBITS; this->_Myoff %= _VBITS; } else { // add non-negative increment - this->_Myoff += _Off; + this->_Myoff += static_cast<_Size_type>(_Off); this->_Myptr += this->_Myoff / _VBITS; this->_Myoff %= _VBITS; } return *this; } - _NODISCARD _Vb_const_iterator operator+(const difference_type _Off) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER _Vb_const_iterator operator+(const difference_type _Off) const noexcept { _Vb_const_iterator _Tmp = *this; return _Tmp += _Off; } - _Vb_const_iterator& operator-=(const difference_type _Off) noexcept { + _CONSTEXPR20_CONTAINER _Vb_const_iterator& operator-=(const difference_type _Off) noexcept { return *this += -_Off; } - _NODISCARD _Vb_const_iterator operator-(const difference_type _Off) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER _Vb_const_iterator operator-(const difference_type _Off) const noexcept { _Vb_const_iterator _Tmp = *this; return _Tmp -= _Off; } - _NODISCARD difference_type operator-(const _Vb_const_iterator& _Right) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER difference_type operator-(const _Vb_const_iterator& _Right) const noexcept { _Compat(_Right); return static_cast(_VBITS * (this->_Myptr - _Right._Myptr)) + static_cast(this->_Myoff) - static_cast(_Right._Myoff); } - _NODISCARD const_reference operator[](const difference_type _Off) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER const_reference operator[](const difference_type _Off) const noexcept { return *(*this + _Off); } - _NODISCARD bool operator==(const _Vb_const_iterator& _Right) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER bool operator==(const _Vb_const_iterator& _Right) const noexcept { _Compat(_Right); return this->_Myptr == _Right._Myptr && this->_Myoff == _Right._Myoff; } - _NODISCARD bool operator!=(const _Vb_const_iterator& _Right) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER bool operator!=(const _Vb_const_iterator& _Right) const noexcept { return !(*this == _Right); } - _NODISCARD bool operator<(const _Vb_const_iterator& _Right) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER bool operator<(const _Vb_const_iterator& _Right) const noexcept { _Compat(_Right); return this->_Myptr < _Right._Myptr || (this->_Myptr == _Right._Myptr && this->_Myoff < _Right._Myoff); } - _NODISCARD bool operator>(const _Vb_const_iterator& _Right) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER bool operator>(const _Vb_const_iterator& _Right) const noexcept { return _Right < *this; } - _NODISCARD bool operator<=(const _Vb_const_iterator& _Right) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER bool operator<=(const _Vb_const_iterator& _Right) const noexcept { return !(_Right < *this); } - _NODISCARD bool operator>=(const _Vb_const_iterator& _Right) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER bool operator>=(const _Vb_const_iterator& _Right) const noexcept { return !(*this < _Right); } - void _Compat(const _Vb_const_iterator& _Right) const noexcept { // test for compatible iterator pair + _CONSTEXPR20_CONTAINER void _Compat( + const _Vb_const_iterator& _Right) const noexcept { // test for compatible iterator pair #if _ITERATOR_DEBUG_LEVEL == 0 (void) _Right; #else // _ITERATOR_DEBUG_LEVEL == 0 - _STL_VERIFY(this->_Getcont() == _Right._Getcont(), "vector iterators incompatible"); +#ifdef __cpp_lib_constexpr_dynamic_alloc + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_constexpr_dynamic_alloc + { + _STL_VERIFY(this->_Getcont() == _Right._Getcont(), "vector iterators incompatible"); + } #endif // _ITERATOR_DEBUG_LEVEL } #if _ITERATOR_DEBUG_LEVEL != 0 using _Prevent_inheriting_unwrap = _Vb_const_iterator; - friend void _Verify_range(const _Vb_const_iterator& _First, const _Vb_const_iterator& _Last) noexcept { + friend _CONSTEXPR20_CONTAINER void _Verify_range( + const _Vb_const_iterator& _First, const _Vb_const_iterator& _Last) noexcept { // note _Compat check inside <= _STL_VERIFY(_First <= _Last, "vector iterator range transposed"); } #endif // _ITERATOR_DEBUG_LEVEL != 0 - void _Dec() noexcept { // decrement bit position + _CONSTEXPR20_CONTAINER void _Dec() noexcept { // decrement bit position #if _ITERATOR_DEBUG_LEVEL != 0 - const auto _Cont = static_cast(this->_Getcont()); - _STL_VERIFY(_Cont, "cannot decrement value-initialized vector iterator"); - _STL_VERIFY(this->_Total_off(_Cont) > 0, "cannot decrement vector begin iterator"); +#ifdef __cpp_lib_constexpr_dynamic_alloc + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_constexpr_dynamic_alloc + { + const auto _Cont = static_cast(this->_Getcont()); + _STL_VERIFY(_Cont, "cannot decrement value-initialized vector iterator"); + _STL_VERIFY(this->_Total_off(_Cont) > 0, "cannot decrement vector begin iterator"); + } #endif // _ITERATOR_DEBUG_LEVEL != 0 if (this->_Myoff != 0) { @@ -2062,12 +2258,17 @@ public: } } - void _Inc() noexcept { // increment bit position + _CONSTEXPR20_CONTAINER void _Inc() noexcept { // increment bit position #if _ITERATOR_DEBUG_LEVEL != 0 - const auto _Cont = static_cast(this->_Getcont()); - _STL_VERIFY(_Cont, "cannot increment value-initialized vector iterator"); - _STL_VERIFY(this->_Total_off(_Cont) < static_cast<_Difference_type>(_Cont->_Mysize), - "cannot increment vector end iterator"); +#ifdef __cpp_lib_constexpr_dynamic_alloc + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_constexpr_dynamic_alloc + { + const auto _Cont = static_cast(this->_Getcont()); + _STL_VERIFY(_Cont, "cannot increment value-initialized vector iterator"); + _STL_VERIFY(this->_Total_off(_Cont) < static_cast<_Difference_type>(_Cont->_Mysize), + "cannot increment vector end iterator"); + } #endif // _ITERATOR_DEBUG_LEVEL != 0 if (this->_Myoff < _VBITS - 1) { @@ -2080,7 +2281,7 @@ public: }; template -_NODISCARD _Vb_const_iterator<_Alvbase_wrapped> operator+( +_NODISCARD _CONSTEXPR20_CONTAINER _Vb_const_iterator<_Alvbase_wrapped> operator+( typename _Vb_const_iterator<_Alvbase_wrapped>::difference_type _Off, _Vb_const_iterator<_Alvbase_wrapped> _Right) noexcept { return _Right += _Off; @@ -2105,62 +2306,67 @@ public: using _Mybase::_Mybase; - _NODISCARD reference operator*() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER reference operator*() const noexcept { #if _ITERATOR_DEBUG_LEVEL != 0 - const auto _Cont = static_cast(this->_Getcont()); - _STL_VERIFY(_Cont, "cannot dereference value-initialized vector iterator"); - _STL_VERIFY(this->_Total_off(_Cont) < static_cast<_Difference_type>(_Cont->_Mysize), - "vector iterator not dereferenceable"); +#ifdef __cpp_lib_constexpr_dynamic_alloc + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_constexpr_dynamic_alloc + { + const auto _Cont = static_cast(this->_Getcont()); + _STL_VERIFY(_Cont, "cannot dereference value-initialized vector iterator"); + _STL_VERIFY(this->_Total_off(_Cont) < static_cast<_Difference_type>(_Cont->_Mysize), + "vector iterator not dereferenceable"); + } #endif // _ITERATOR_DEBUG_LEVEL != 0 return _Reft(*this); } - _Vb_iterator& operator++() noexcept { + _CONSTEXPR20_CONTAINER _Vb_iterator& operator++() noexcept { _Mybase::operator++(); return *this; } - _Vb_iterator operator++(int) noexcept { + _CONSTEXPR20_CONTAINER _Vb_iterator operator++(int) noexcept { _Vb_iterator _Tmp = *this; _Mybase::operator++(); return _Tmp; } - _Vb_iterator& operator--() noexcept { + _CONSTEXPR20_CONTAINER _Vb_iterator& operator--() noexcept { _Mybase::operator--(); return *this; } - _Vb_iterator operator--(int) noexcept { + _CONSTEXPR20_CONTAINER _Vb_iterator operator--(int) noexcept { _Vb_iterator _Tmp = *this; _Mybase::operator--(); return _Tmp; } - _Vb_iterator& operator+=(const difference_type _Off) noexcept { + _CONSTEXPR20_CONTAINER _Vb_iterator& operator+=(const difference_type _Off) noexcept { _Mybase::operator+=(_Off); return *this; } - _NODISCARD _Vb_iterator operator+(const difference_type _Off) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER _Vb_iterator operator+(const difference_type _Off) const noexcept { _Vb_iterator _Tmp = *this; return _Tmp += _Off; } - _Vb_iterator& operator-=(const difference_type _Off) noexcept { + _CONSTEXPR20_CONTAINER _Vb_iterator& operator-=(const difference_type _Off) noexcept { _Mybase::operator-=(_Off); return *this; } using _Mybase::operator-; - _NODISCARD _Vb_iterator operator-(const difference_type _Off) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER _Vb_iterator operator-(const difference_type _Off) const noexcept { _Vb_iterator _Tmp = *this; return _Tmp -= _Off; } - _NODISCARD reference operator[](const difference_type _Off) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER reference operator[](const difference_type _Off) const noexcept { return *(*this + _Off); } @@ -2168,7 +2374,7 @@ public: }; template -_NODISCARD _Vb_iterator<_Alvbase_wrapped> operator+( +_NODISCARD _CONSTEXPR20_CONTAINER _Vb_iterator<_Alvbase_wrapped> operator+( typename _Vb_iterator<_Alvbase_wrapped>::difference_type _Off, _Vb_iterator<_Alvbase_wrapped> _Right) noexcept { return _Right += _Off; } @@ -2183,39 +2389,41 @@ public: using _Alvbase_wrapped = _Wrap_alloc<_Alvbase>; using size_type = typename _Alvbase_traits::size_type; - _Vb_val() noexcept(is_nothrow_default_constructible_v<_Vectype>) : _Myvec(), _Mysize(0) { + _CONSTEXPR20_CONTAINER _Vb_val() noexcept(is_nothrow_default_constructible_v<_Vectype>) : _Myvec(), _Mysize(0) { this->_Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alvbase, _Getal())); } - _Vb_val(const _Alloc& _Al) noexcept(is_nothrow_constructible_v<_Vectype, _Alvbase>) + _CONSTEXPR20_CONTAINER _Vb_val(const _Alloc& _Al) noexcept(is_nothrow_constructible_v<_Vectype, _Alvbase>) : _Myvec(static_cast<_Alvbase>(_Al)), _Mysize(0) { this->_Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alvbase, _Getal())); } - _Vb_val(size_type _Count, const bool& _Val) : _Myvec(_Nw(_Count), static_cast<_Vbase>(_Val ? -1 : 0)), _Mysize(0) { + _CONSTEXPR20_CONTAINER _Vb_val(size_type _Count, const bool& _Val) + : _Myvec(_Nw(_Count), static_cast<_Vbase>(_Val ? -1 : 0)), _Mysize(0) { this->_Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alvbase, _Getal())); } - _Vb_val(size_type _Count, const bool& _Val, const _Alloc& _Al) + _CONSTEXPR20_CONTAINER _Vb_val(size_type _Count, const bool& _Val, const _Alloc& _Al) : _Myvec(_Nw(_Count), static_cast<_Vbase>(_Val ? -1 : 0), static_cast<_Alvbase>(_Al)), _Mysize(0) { this->_Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alvbase, _Getal())); } - _Vb_val(const _Vb_val& _Right) : _Myvec(_Right._Myvec), _Mysize(_Right._Mysize) { + _CONSTEXPR20_CONTAINER _Vb_val(const _Vb_val& _Right) : _Myvec(_Right._Myvec), _Mysize(_Right._Mysize) { this->_Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alvbase, _Getal())); } - _Vb_val(const _Vb_val& _Right, const _Alloc& _Al) + _CONSTEXPR20_CONTAINER _Vb_val(const _Vb_val& _Right, const _Alloc& _Al) : _Myvec(_Right._Myvec, static_cast<_Alvbase>(_Al)), _Mysize(_Right._Mysize) { this->_Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alvbase, _Getal())); } - _Vb_val(_Vb_val&& _Right) noexcept(is_nothrow_move_constructible_v<_Vectype>) + _CONSTEXPR20_CONTAINER _Vb_val(_Vb_val&& _Right) noexcept(is_nothrow_move_constructible_v<_Vectype>) : _Myvec(_STD move(_Right._Myvec)), _Mysize(_STD exchange(_Right._Mysize, size_type{0})) { this->_Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alvbase, _Getal())); } - _Vb_val(_Vb_val&& _Right, const _Alloc& _Al) noexcept(is_nothrow_constructible_v<_Vectype, _Vectype, _Alvbase>) + _CONSTEXPR20_CONTAINER _Vb_val(_Vb_val&& _Right, const _Alloc& _Al) noexcept( + is_nothrow_constructible_v<_Vectype, _Vectype, _Alvbase>) : _Myvec(_STD move(_Right._Myvec), static_cast<_Alvbase>(_Al)), _Mysize(_Right._Mysize) { if (_Right._Myvec.empty()) { // we took _Right's buffer, so zero out size @@ -2225,7 +2433,7 @@ public: this->_Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alvbase, _Getal())); } - ~_Vb_val() noexcept { + _CONSTEXPR20_CONTAINER ~_Vb_val() noexcept { #if _ITERATOR_DEBUG_LEVEL != 0 this->_Orphan_all(); auto&& _Alproxy = _GET_PROXY_ALLOCATOR(_Alvbase, this->_Getal()); @@ -2233,15 +2441,15 @@ public: #endif // _ITERATOR_DEBUG_LEVEL != 0 } - _Alvbase& _Getal() noexcept { + _CONSTEXPR20_CONTAINER _Alvbase& _Getal() noexcept { return _Myvec._Getal(); } - const _Alvbase& _Getal() const noexcept { + _CONSTEXPR20_CONTAINER const _Alvbase& _Getal() const noexcept { return _Myvec._Getal(); } - static size_type _Nw(size_type _Count) noexcept { + static _CONSTEXPR20_CONTAINER size_type _Nw(size_type _Count) noexcept { return (_Count + _VBITS - 1) / _VBITS; } @@ -2281,41 +2489,44 @@ public: static const int _VBITS = _STD _VBITS; enum { _EEN_VBITS = _VBITS }; // helper for expression evaluator - vector() noexcept(is_nothrow_default_constructible_v<_Mybase>) // strengthened + _CONSTEXPR20_CONTAINER vector() noexcept(is_nothrow_default_constructible_v<_Mybase>) // strengthened : _Mybase() {} - explicit vector(const _Alloc& _Al) noexcept(is_nothrow_constructible_v<_Mybase, const _Alloc&>) // strengthened + _CONSTEXPR20_CONTAINER explicit vector(const _Alloc& _Al) noexcept( + is_nothrow_constructible_v<_Mybase, const _Alloc&>) // strengthened : _Mybase(_Al) {} - explicit vector(_CRT_GUARDOVERFLOW size_type _Count, const _Alloc& _Al = _Alloc()) : _Mybase(_Count, false, _Al) { + _CONSTEXPR20_CONTAINER explicit vector(_CRT_GUARDOVERFLOW size_type _Count, const _Alloc& _Al = _Alloc()) + : _Mybase(_Count, false, _Al) { _Trim(_Count); } - vector(_CRT_GUARDOVERFLOW size_type _Count, const bool& _Val, const _Alloc& _Al = _Alloc()) + _CONSTEXPR20_CONTAINER vector(_CRT_GUARDOVERFLOW size_type _Count, const bool& _Val, const _Alloc& _Al = _Alloc()) : _Mybase(_Count, _Val, _Al) { _Trim(_Count); } - vector(const vector& _Right) : _Mybase(_Right) {} + _CONSTEXPR20_CONTAINER vector(const vector& _Right) : _Mybase(_Right) {} - vector(const vector& _Right, const _Alloc& _Al) : _Mybase(_Right, _Al) {} + _CONSTEXPR20_CONTAINER vector(const vector& _Right, const _Alloc& _Al) : _Mybase(_Right, _Al) {} template , int> = 0> - vector(_Iter _First, _Iter _Last, const _Alloc& _Al = _Alloc()) : _Mybase(_Al) { + _CONSTEXPR20_CONTAINER vector(_Iter _First, _Iter _Last, const _Alloc& _Al = _Alloc()) : _Mybase(_Al) { _BConstruct(_First, _Last); } template - void _BConstruct(_Iter _First, _Iter _Last) { + _CONSTEXPR20_CONTAINER void _BConstruct(_Iter _First, _Iter _Last) { insert(begin(), _First, _Last); } - vector(vector&& _Right) noexcept(is_nothrow_move_constructible_v<_Mybase>) // strengthened + _CONSTEXPR20_CONTAINER vector(vector&& _Right) noexcept(is_nothrow_move_constructible_v<_Mybase>) // strengthened : _Mybase(_STD move(_Right)) { this->_Swap_proxy_and_iterators(_Right); } - vector(vector&& _Right, const _Alloc& _Al) noexcept(is_nothrow_constructible_v<_Mybase, _Mybase, const _Alloc&>) + _CONSTEXPR20_CONTAINER vector(vector&& _Right, const _Alloc& _Al) noexcept( + is_nothrow_constructible_v<_Mybase, _Mybase, const _Alloc&>) : _Mybase(_STD move(_Right), _Al) { if constexpr (!_Alvbase_traits::is_always_equal::value) { if (this->_Getal() != _Right._Getal()) { @@ -2328,13 +2539,13 @@ public: private: #if _ITERATOR_DEBUG_LEVEL != 0 - void _Move_assign(vector& _Right, _Equal_allocators) noexcept { + _CONSTEXPR20_CONTAINER void _Move_assign(vector& _Right, _Equal_allocators) noexcept { this->_Myvec = _STD move(_Right._Myvec); this->_Mysize = _STD exchange(_Right._Mysize, size_type{0}); this->_Swap_proxy_and_iterators(_Right); } - void _Move_assign(vector& _Right, _Propagate_allocators) noexcept { + _CONSTEXPR20_CONTAINER void _Move_assign(vector& _Right, _Propagate_allocators) noexcept { using _Alproxy_type = _Rebind_alloc_t<_Alvbase, _Container_proxy>; if (this->_Getal() != _Right._Getal()) { // reload proxy // intentionally slams into noexcept on OOM, TRANSITION, VSO-466800 @@ -2353,7 +2564,7 @@ private: this->_Swap_proxy_and_iterators(_Right); } - void _Move_assign(vector& _Right, _No_propagate_allocators) { + _CONSTEXPR20_CONTAINER void _Move_assign(vector& _Right, _No_propagate_allocators) { this->_Myvec = _STD move(_Right._Myvec); this->_Mysize = _Right._Mysize; if (_Right._Myvec.empty()) { @@ -2368,7 +2579,7 @@ private: #endif // _ITERATOR_DEBUG_LEVEL != 0 public: - vector& operator=(vector&& _Right) noexcept(is_nothrow_move_assignable_v<_Mybase>) { + _CONSTEXPR20_CONTAINER vector& operator=(vector&& _Right) noexcept(is_nothrow_move_assignable_v<_Mybase>) { if (this != _STD addressof(_Right)) { #if _ITERATOR_DEBUG_LEVEL == 0 this->_Myvec = _STD move(_Right._Myvec); @@ -2382,7 +2593,7 @@ public: } template - decltype(auto) emplace_back(_Valty&&... _Val) { + _CONSTEXPR20_CONTAINER decltype(auto) emplace_back(_Valty&&... _Val) { bool _Tmp(_STD forward<_Valty>(_Val)...); push_back(_Tmp); @@ -2392,38 +2603,39 @@ public: } template - iterator emplace(const_iterator _Where, _Valty&&... _Val) { + _CONSTEXPR20_CONTAINER iterator emplace(const_iterator _Where, _Valty&&... _Val) { bool _Tmp(_STD forward<_Valty>(_Val)...); return insert(_Where, _Tmp); } - vector(initializer_list _Ilist, const _Alloc& _Al = allocator_type()) : _Mybase(0, false, _Al) { + _CONSTEXPR20_CONTAINER vector(initializer_list _Ilist, const _Alloc& _Al = allocator_type()) + : _Mybase(0, false, _Al) { insert(begin(), _Ilist.begin(), _Ilist.end()); } - vector& operator=(initializer_list _Ilist) { + _CONSTEXPR20_CONTAINER vector& operator=(initializer_list _Ilist) { assign(_Ilist.begin(), _Ilist.end()); return *this; } - void assign(initializer_list _Ilist) { + _CONSTEXPR20_CONTAINER void assign(initializer_list _Ilist) { assign(_Ilist.begin(), _Ilist.end()); } - iterator insert(const_iterator _Where, initializer_list _Ilist) { + _CONSTEXPR20_CONTAINER iterator insert(const_iterator _Where, initializer_list _Ilist) { return insert(_Where, _Ilist.begin(), _Ilist.end()); } - ~vector() noexcept {} + _CONSTEXPR20_CONTAINER ~vector() noexcept {} private: #if _ITERATOR_DEBUG_LEVEL != 0 - void _Copy_assign(const vector& _Right, false_type) { + _CONSTEXPR20_CONTAINER void _Copy_assign(const vector& _Right, false_type) { this->_Myvec = _Right._Myvec; this->_Mysize = _Right._Mysize; } - void _Copy_assign(const vector& _Right, true_type) { + _CONSTEXPR20_CONTAINER void _Copy_assign(const vector& _Right, true_type) { if (this->_Getal() == _Right._Getal()) { _Copy_assign(_Right, false_type{}); } else { @@ -2440,7 +2652,7 @@ private: #endif // _ITERATOR_DEBUG_LEVEL != 0 public: - vector& operator=(const vector& _Right) { + _CONSTEXPR20_CONTAINER vector& operator=(const vector& _Right) { if (this != _STD addressof(_Right)) { #if _ITERATOR_DEBUG_LEVEL == 0 this->_Myvec = _Right._Myvec; @@ -2454,70 +2666,70 @@ public: return *this; } - void reserve(_CRT_GUARDOVERFLOW size_type _Count) { + _CONSTEXPR20_CONTAINER void reserve(_CRT_GUARDOVERFLOW size_type _Count) { this->_Myvec.reserve(this->_Nw(_Count)); } - _NODISCARD size_type capacity() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER size_type capacity() const noexcept { return this->_Myvec.capacity() * _VBITS; } - _NODISCARD iterator begin() noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER iterator begin() noexcept { return iterator(this->_Myvec.data(), this); } - _NODISCARD const_iterator begin() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER const_iterator begin() const noexcept { return const_iterator(this->_Myvec.data(), this); } - _NODISCARD iterator end() noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER iterator end() noexcept { return begin() + static_cast(this->_Mysize); } - _NODISCARD const_iterator end() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER const_iterator end() const noexcept { return begin() + static_cast(this->_Mysize); } - _NODISCARD const_iterator cbegin() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER const_iterator cbegin() const noexcept { return begin(); } - _NODISCARD const_iterator cend() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER const_iterator cend() const noexcept { return end(); } - _NODISCARD const_reverse_iterator crbegin() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER const_reverse_iterator crbegin() const noexcept { return rbegin(); } - _NODISCARD const_reverse_iterator crend() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER const_reverse_iterator crend() const noexcept { return rend(); } - _NODISCARD iterator _Unchecked_begin() noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER iterator _Unchecked_begin() noexcept { return iterator(this->_Myvec.data(), this); } - _NODISCARD const_iterator _Unchecked_begin() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER const_iterator _Unchecked_begin() const noexcept { return const_iterator(this->_Myvec.data(), this); } - _NODISCARD iterator _Unchecked_end() noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER iterator _Unchecked_end() noexcept { return _Unchecked_begin() + static_cast(this->_Mysize); } - _NODISCARD const_iterator _Unchecked_end() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER const_iterator _Unchecked_end() const noexcept { return _Unchecked_begin() + static_cast(this->_Mysize); } - void shrink_to_fit() { + _CONSTEXPR20_CONTAINER void shrink_to_fit() { if (this->_Myvec.capacity() != this->_Myvec.size()) { this->_Orphan_all(); this->_Myvec.shrink_to_fit(); } } - iterator _Make_iter(const_iterator _Where) noexcept { + _CONSTEXPR20_CONTAINER iterator _Make_iter(const_iterator _Where) noexcept { iterator _Tmp = begin(); if (0 < this->_Mysize) { _Tmp += _Where - begin(); @@ -2526,23 +2738,23 @@ public: return _Tmp; } - _NODISCARD reverse_iterator rbegin() noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER reverse_iterator rbegin() noexcept { return reverse_iterator(end()); } - _NODISCARD const_reverse_iterator rbegin() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); } - _NODISCARD reverse_iterator rend() noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER reverse_iterator rend() noexcept { return reverse_iterator(begin()); } - _NODISCARD const_reverse_iterator rend() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); } - void resize(_CRT_GUARDOVERFLOW size_type _Newsize, bool _Val = false) { + _CONSTEXPR20_CONTAINER void resize(_CRT_GUARDOVERFLOW size_type _Newsize, bool _Val = false) { if (size() < _Newsize) { _Insert_n(end(), _Newsize - size(), _Val); } else if (_Newsize < size()) { @@ -2550,11 +2762,11 @@ public: } } - _NODISCARD size_type size() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER size_type size() const noexcept { return this->_Mysize; } - _NODISCARD size_type max_size() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER size_type max_size() const noexcept { constexpr auto _Diff_max = static_cast((numeric_limits::max)()); const size_type _Ints_max = this->_Myvec.max_size(); if (_Ints_max > _Diff_max / _VBITS) { // max_size bound by difference_type limits @@ -2565,15 +2777,15 @@ public: return _Ints_max * _VBITS; } - _NODISCARD bool empty() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER bool empty() const noexcept { return size() == 0; } - _NODISCARD allocator_type get_allocator() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER allocator_type get_allocator() const noexcept { return static_cast(this->_Myvec.get_allocator()); } - _NODISCARD const_reference at(size_type _Off) const { + _NODISCARD _CONSTEXPR20_CONTAINER const_reference at(size_type _Off) const { if (size() <= _Off) { _Xran(); } @@ -2581,7 +2793,7 @@ public: return (*this)[_Off]; } - _NODISCARD reference at(size_type _Off) { + _NODISCARD _CONSTEXPR20_CONTAINER reference at(size_type _Off) { if (size() <= _Off) { _Xran(); } @@ -2589,7 +2801,7 @@ public: return (*this)[_Off]; } - _NODISCARD const_reference operator[](size_type _Off) const noexcept /* strengthened */ { + _NODISCARD _CONSTEXPR20_CONTAINER const_reference operator[](size_type _Off) const noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Off < this->_Mysize, "vector subscript out of range"); #endif // _CONTAINER_DEBUG_LEVEL > 0 @@ -2599,7 +2811,7 @@ public: return *_It; } - _NODISCARD reference operator[](size_type _Off) noexcept /* strengthened */ { + _NODISCARD _CONSTEXPR20_CONTAINER reference operator[](size_type _Off) noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Off < this->_Mysize, "vector subscript out of range"); #endif // _CONTAINER_DEBUG_LEVEL > 0 @@ -2609,7 +2821,7 @@ public: return *_It; } - _NODISCARD reference front() noexcept /* strengthened */ { + _NODISCARD _CONSTEXPR20_CONTAINER reference front() noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(this->_Mysize != 0, "front() called on empty vector"); #endif // _CONTAINER_DEBUG_LEVEL > 0 @@ -2617,7 +2829,7 @@ public: return *begin(); } - _NODISCARD const_reference front() const noexcept /* strengthened */ { + _NODISCARD _CONSTEXPR20_CONTAINER const_reference front() const noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(this->_Mysize != 0, "front() called on empty vector"); #endif // _CONTAINER_DEBUG_LEVEL > 0 @@ -2625,7 +2837,7 @@ public: return *begin(); } - _NODISCARD reference back() noexcept /* strengthened */ { + _NODISCARD _CONSTEXPR20_CONTAINER reference back() noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(this->_Mysize != 0, "back() called on empty vector"); #endif // _CONTAINER_DEBUG_LEVEL > 0 @@ -2633,7 +2845,7 @@ public: return *(end() - 1); } - _NODISCARD const_reference back() const noexcept /* strengthened */ { + _NODISCARD _CONSTEXPR20_CONTAINER const_reference back() const noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(this->_Mysize != 0, "back() called on empty vector"); #endif // _CONTAINER_DEBUG_LEVEL > 0 @@ -2641,42 +2853,43 @@ public: return *(end() - 1); } - void push_back(const bool& _Val) { + _CONSTEXPR20_CONTAINER void push_back(const bool& _Val) { insert(end(), _Val); } - void pop_back() noexcept /* strengthened */ { + _CONSTEXPR20_CONTAINER void pop_back() noexcept /* strengthened */ { erase(end() - 1); } template , int> = 0> - void assign(_Iter _First, _Iter _Last) { + _CONSTEXPR20_CONTAINER void assign(_Iter _First, _Iter _Last) { clear(); insert(begin(), _First, _Last); } - void assign(_CRT_GUARDOVERFLOW size_type _Count, const bool& _Val) { + _CONSTEXPR20_CONTAINER void assign(_CRT_GUARDOVERFLOW size_type _Count, const bool& _Val) { clear(); _Insert_n(begin(), _Count, _Val); } - iterator insert(const_iterator _Where, const bool& _Val) { + _CONSTEXPR20_CONTAINER iterator insert(const_iterator _Where, const bool& _Val) { return _Insert_n(_Where, static_cast(1), _Val); } - iterator insert(const_iterator _Where, _CRT_GUARDOVERFLOW size_type _Count, const bool& _Val) { + _CONSTEXPR20_CONTAINER iterator insert( + const_iterator _Where, _CRT_GUARDOVERFLOW size_type _Count, const bool& _Val) { return _Insert_n(_Where, _Count, _Val); } template , int> = 0> - iterator insert(const_iterator _Where, _Iter _First, _Iter _Last) { + _CONSTEXPR20_CONTAINER iterator insert(const_iterator _Where, _Iter _First, _Iter _Last) { difference_type _Off = _Where - begin(); _Insert(_Where, _First, _Last, _Iter_cat_t<_Iter>{}); return begin() + _Off; } template - void _Insert(const_iterator _Where, _Iter _First, _Iter _Last, input_iterator_tag) { + _CONSTEXPR20_CONTAINER void _Insert(const_iterator _Where, _Iter _First, _Iter _Last, input_iterator_tag) { difference_type _Off = _Where - begin(); for (; _First != _Last; ++_First, (void) ++_Off) { @@ -2685,14 +2898,14 @@ public: } template - void _Insert(const_iterator _Where, _Iter _First, _Iter _Last, forward_iterator_tag) { + _CONSTEXPR20_CONTAINER void _Insert(const_iterator _Where, _Iter _First, _Iter _Last, forward_iterator_tag) { _Adl_verify_range(_First, _Last); auto _Count = _Convert_size(static_cast(_STD distance(_First, _Last))); size_type _Off = _Insert_x(_Where, _Count); _Copy_unchecked(_Get_unwrapped(_First), _Get_unwrapped(_Last), begin() + static_cast(_Off)); } - iterator erase(const_iterator _Where_arg) noexcept /* strengthened */ { + _CONSTEXPR20_CONTAINER iterator erase(const_iterator _Where_arg) noexcept /* strengthened */ { iterator _Where = _Make_iter(_Where_arg); difference_type _Off = _Where - begin(); @@ -2709,7 +2922,8 @@ public: return begin() + _Off; } - iterator erase(const_iterator _First_arg, const_iterator _Last_arg) noexcept /* strengthened */ { + _CONSTEXPR20_CONTAINER iterator erase(const_iterator _First_arg, const_iterator _Last_arg) noexcept + /* strengthened */ { iterator _First = _Make_iter(_First_arg); iterator _Last = _Make_iter(_Last_arg); difference_type _Off = _First - begin(); @@ -2730,13 +2944,13 @@ public: return begin() + _Off; } - void clear() noexcept { + _CONSTEXPR20_CONTAINER void clear() noexcept { this->_Orphan_all(); this->_Myvec.clear(); this->_Mysize = 0; } - void flip() noexcept { // toggle all elements + _CONSTEXPR20_CONTAINER void flip() noexcept { // toggle all elements for (auto& _Elem : this->_Myvec) { _Elem = ~_Elem; } @@ -2744,7 +2958,7 @@ public: _Trim(this->_Mysize); } - void swap(vector& _Right) noexcept /* strengthened */ { + _CONSTEXPR20_CONTAINER void swap(vector& _Right) noexcept /* strengthened */ { if (this != _STD addressof(_Right)) { this->_Swap_proxy_and_iterators(_Right); this->_Myvec.swap(_Right._Myvec); @@ -2752,7 +2966,7 @@ public: } } - static void swap(reference _Left, reference _Right) noexcept { + static _CONSTEXPR20_CONTAINER void swap(reference _Left, reference _Right) noexcept { bool _Val = _Left; // NOT _STD swap _Left = _Right; _Right = _Val; @@ -2760,14 +2974,14 @@ public: friend hash>; - iterator _Insert_n(const_iterator _Where, size_type _Count, const bool& _Val) { + _CONSTEXPR20_CONTAINER iterator _Insert_n(const_iterator _Where, size_type _Count, const bool& _Val) { size_type _Off = _Insert_x(_Where, _Count); const auto _Result = begin() + static_cast(_Off); _STD fill(_Result, _Result + static_cast(_Count), _Val); return _Result; } - size_type _Insert_x(const_iterator _Where, size_type _Count) { + _CONSTEXPR20_CONTAINER size_type _Insert_x(const_iterator _Where, size_type _Count) { difference_type _Off = _Where - begin(); #if _ITERATOR_DEBUG_LEVEL == 2 @@ -2799,7 +3013,7 @@ public: } #if _ITERATOR_DEBUG_LEVEL == 2 - void _Orphan_range(size_type _Offlo, size_type _Offhi) const { + void _Orphan_range_locked(size_type _Offlo, size_type _Offhi) const { _Lockit _Lock(_LOCK_DEBUG); const auto _Base = this->_Myvec.data(); @@ -2816,11 +3030,17 @@ public: } } -#else // _ITERATOR_DEBUG_LEVEL == 2 - void _Orphan_range(size_type, size_type) const {} + _CONSTEXPR20_CONTAINER void _Orphan_range(size_type _Offlo, size_type _Offhi) const { +#ifdef __cpp_lib_constexpr_dynamic_alloc + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_constexpr_dynamic_alloc + { + _Orphan_range_locked(_Offlo, _Offhi); + } + } #endif // _ITERATOR_DEBUG_LEVEL == 2 - void _Trim(size_type _Size) { + _CONSTEXPR20_CONTAINER void _Trim(size_type _Size) { if (max_size() < _Size) { _Xlen(); // result too long } @@ -2847,12 +3067,14 @@ public: }; template -_NODISCARD bool operator==(const vector& _Left, const vector& _Right) { +_NODISCARD _CONSTEXPR20_CONTAINER bool operator==( + const vector& _Left, const vector& _Right) { return _Left.size() == _Right.size() && _Left._Myvec == _Right._Myvec; } template -_NODISCARD bool operator!=(const vector& _Left, const vector& _Right) { +_NODISCARD _CONSTEXPR20_CONTAINER bool operator!=( + const vector& _Left, const vector& _Right) { return !(_Left == _Right); } @@ -2862,19 +3084,19 @@ struct hash> { _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef vector _ARGUMENT_TYPE_NAME; _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef size_t _RESULT_TYPE_NAME; - _NODISCARD size_t operator()(const vector& _Keyval) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER size_t operator()(const vector& _Keyval) const noexcept { return _Hash_array_representation(_Keyval._Myvec.data(), _Keyval._Myvec.size()); } }; #if _HAS_CXX20 template -typename vector<_Ty, _Alloc>::size_type erase(vector<_Ty, _Alloc>& _Cont, const _Uty& _Val) { +_CONSTEXPR20_CONTAINER typename vector<_Ty, _Alloc>::size_type erase(vector<_Ty, _Alloc>& _Cont, const _Uty& _Val) { return _Erase_remove(_Cont, _Val); } template -typename vector<_Ty, _Alloc>::size_type erase_if(vector<_Ty, _Alloc>& _Cont, _Pr _Pred) { +_CONSTEXPR20_CONTAINER typename vector<_Ty, _Alloc>::size_type erase_if(vector<_Ty, _Alloc>& _Cont, _Pr _Pred) { return _Erase_remove_if(_Cont, _Pass_fn(_Pred)); } #endif // _HAS_CXX20 @@ -2920,13 +3142,13 @@ _CONSTEXPR20 void _Fill_vbool(_FwdIt _First, _FwdIt _Last, const _Ty& _Val) { *_VbFirst = (*_VbFirst & _FirstDestMask) | (_FillVal & _FirstSourceMask); ++_VbFirst; -#ifdef __cpp_lib_is_constant_evaluated +#ifdef __cpp_lib_constexpr_dynamic_alloc if (_STD is_constant_evaluated()) { for (; _VbFirst != _VbLast; ++_VbFirst) { *_VbFirst = _FillVal; } } else -#endif // __cpp_lib_is_constant_evaluated +#endif // __cpp_lib_constexpr_dynamic_alloc { const auto _VbFirst_ch = reinterpret_cast(_VbFirst); const auto _VbLast_ch = reinterpret_cast(_VbLast); diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index 72b2d93e095..94033b70d71 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -178,6 +178,7 @@ // P0919R3 Heterogeneous Lookup For Unordered Containers // P0966R1 string::reserve() Should Not Shrink // P1001R2 execution::unseq +// P1004R2 constexpr std::vector // P1006R1 constexpr For pointer_traits::pointer_to() // P1007R3 assume_aligned() // P1020R1 Smart Pointer Creation With Default Initialization @@ -1195,6 +1196,10 @@ #define __cpp_lib_constexpr_tuple 201811L #define __cpp_lib_constexpr_utility 201811L +#if defined(__cpp_constexpr_dynamic_alloc) && !defined(__clang__) // TRANSITION, LLVM-48606 +#define __cpp_lib_constexpr_vector 201907L +#endif // __cpp_constexpr_dynamic_alloc && !__clang__ + #ifdef __cpp_impl_coroutine // TRANSITION, Clang coroutine support #define __cpp_lib_coroutine 201902L #endif // __cpp_impl_coroutine diff --git a/tests/std/test.lst b/tests/std/test.lst index 014d2c798d4..9ec33bcb17e 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -254,6 +254,7 @@ tests\P0758R1_is_nothrow_convertible tests\P0768R1_spaceship_cpos tests\P0768R1_spaceship_operator tests\P0769R2_shift_left_shift_right +tests\P0784R7_library_machinery tests\P0784R7_library_support_for_more_constexpr_containers tests\P0811R3_midpoint_lerp tests\P0896R4_common_iterator @@ -370,6 +371,8 @@ tests\P0898R3_identity tests\P0912R5_coroutine tests\P0919R3_heterogeneous_unordered_lookup tests\P0966R1_string_reserve_should_not_shrink +tests\P1004R2_constexpr_vector +tests\P1004R2_constexpr_vector_bool tests\P1007R3_assume_aligned tests\P1020R1_smart_pointer_for_overwrite tests\P1023R0_constexpr_for_array_comparisons diff --git a/tests/std/tests/P0784R7_library_machinery/env.lst b/tests/std/tests/P0784R7_library_machinery/env.lst new file mode 100644 index 00000000000..642f530ffad --- /dev/null +++ b/tests/std/tests/P0784R7_library_machinery/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\usual_latest_matrix.lst diff --git a/tests/std/tests/P0784R7_library_machinery/test.cpp b/tests/std/tests/P0784R7_library_machinery/test.cpp new file mode 100644 index 00000000000..b5dd430f7c5 --- /dev/null +++ b/tests/std/tests/P0784R7_library_machinery/test.cpp @@ -0,0 +1,147 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include + +#pragma warning(disable : 4582) // '%s': constructor is not implicitly called +#pragma warning(disable : 4583) // '%s': destructor is not implicitly called + +using namespace std; + +struct int_wrapper_copy { + constexpr int_wrapper_copy() = default; + constexpr int_wrapper_copy(const int v) : _val(v){}; + + constexpr int_wrapper_copy(const int_wrapper_copy& other) : _val(other._val) {} + constexpr int_wrapper_copy& operator=(const int_wrapper_copy& other) { + _val = other._val; + return *this; + } + + constexpr int_wrapper_copy(int_wrapper_copy&&) = delete; + constexpr int_wrapper_copy& operator=(int_wrapper_copy&&) = delete; + + constexpr bool operator==(const int_wrapper_copy&) const = default; + + int _val = 0; +}; + +struct int_wrapper_move { + constexpr int_wrapper_move() = default; + constexpr int_wrapper_move(const int v) : _val(v){}; + + constexpr int_wrapper_move(const int_wrapper_move&) = delete; + constexpr int_wrapper_move& operator=(const int_wrapper_move&) = delete; + + constexpr int_wrapper_move(int_wrapper_move&& other) : _val(exchange(other._val, -1)) {} + constexpr int_wrapper_move& operator=(int_wrapper_move&& other) { + _val = exchange(other._val, -1); + return *this; + } + + constexpr bool operator==(const int_wrapper_move&) const = default; + + int _val = 0; +}; + +static constexpr int_wrapper_copy expected_copy[] = {1, 2, 3, 4}; +static constexpr int_wrapper_move expected_move[] = {1, 2, 3, 4}; +static constexpr int_wrapper_move expected_after_move[] = {-1, -1, -1, -1}; + +constexpr bool test() { + { // _Copy_unchecked + int_wrapper_copy input[] = {1, 2, 3, 4}; + int_wrapper_copy output[4] = {5, 6, 7, 8}; + + const auto result = _Copy_unchecked(begin(input), end(input), begin(output)); + static_assert(is_same_v, int_wrapper_copy*>); + assert(result == end(output)); + assert(equal(begin(expected_copy), end(expected_copy), begin(output), end(output))); + } + + { // _Copy_backward_unchecked + int_wrapper_copy input[] = {1, 2, 3, 4}; + int_wrapper_copy output[4] = {5, 6, 7, 8}; + + const auto result = _Copy_backward_unchecked(begin(input), end(input), end(output)); + static_assert(is_same_v, int_wrapper_copy*>); + assert(result == begin(output)); + assert(equal(begin(expected_copy), end(expected_copy), begin(output), end(output))); + } + +#if _HAS_CXX20 && defined(__cpp_constexpr_dynamic_alloc) && defined(__clang__) + { // _Uninitialized_copy_unchecked + int_wrapper_copy input[] = {1, 2, 3, 4}; + int_wrapper_copy output[4]; + + const auto result = _Uninitialized_copy_unchecked(begin(input), end(input), begin(output)); + static_assert(is_same_v, int_wrapper_copy*>); + assert(result == end(output)); + assert(equal(begin(expected_copy), end(expected_copy), begin(output), end(output))); + } +#endif // _HAS_CXX20 && defined(__cpp_constexpr_dynamic_alloc) + + { // _Move_unchecked + int_wrapper_move input[] = {1, 2, 3, 4}; + int_wrapper_move output[4] = {5, 6, 7, 8}; + + const auto result = _Move_unchecked(begin(input), end(input), begin(output)); + static_assert(is_same_v, int_wrapper_move*>); + assert(result == end(output)); + assert(equal(begin(expected_move), end(expected_move), begin(output), end(output))); + if (is_constant_evaluated()) { + assert(equal(begin(input), end(input), begin(expected_after_move), end(expected_after_move))); + } + } + + { // _Move_backward_unchecked + int_wrapper_move input[] = {1, 2, 3, 4}; + int_wrapper_move output[4] = {5, 6, 7, 8}; + + const auto result = _Move_backward_unchecked(begin(input), end(input), end(output)); + static_assert(is_same_v, int_wrapper_move*>); + assert(result == begin(output)); + assert(equal(begin(expected_move), end(expected_move), begin(output), end(output))); + if (is_constant_evaluated()) { + assert(equal(begin(input), end(input), begin(expected_after_move), end(expected_after_move))); + } + } + +#ifdef __cpp_lib_concepts + { // _Move_backward_common + int_wrapper_move input[] = {1, 2, 3, 4}; + int_wrapper_move output[4] = {5, 6, 7, 8}; + + const auto result = ranges::_Move_backward_common(begin(input), end(input), end(output)); + static_assert(is_same_v, int_wrapper_move*>); + assert(result == begin(output)); + assert(equal(begin(expected_move), end(expected_move), begin(output), end(output))); + if (is_constant_evaluated()) { + assert(equal(begin(input), end(input), begin(expected_after_move), end(expected_after_move))); + } + } +#endif // __cpp_lib_concepts + +#if _HAS_CXX20 && defined(__cpp_constexpr_dynamic_alloc) && defined(__clang__) + { // _Uninitialized_move_unchecked + int_wrapper_move input[] = {1, 2, 3, 4}; + int_wrapper_move output[4]; + + const auto result = _Uninitialized_move_unchecked(begin(input), end(input), begin(output)); + static_assert(is_same_v, int_wrapper_move*>); + assert(result == end(output)); + assert(equal(begin(expected_move), end(expected_move), begin(output), end(output))); + if (is_constant_evaluated()) { + assert(equal(begin(input), end(input), begin(expected_after_move), end(expected_after_move))); + } + } +#endif // _HAS_CXX20 && defined(__cpp_constexpr_dynamic_alloc) + return true; +} + +int main() { + test(); + static_assert(test()); +} diff --git a/tests/std/tests/P1004R2_constexpr_vector/env.lst b/tests/std/tests/P1004R2_constexpr_vector/env.lst new file mode 100644 index 00000000000..642f530ffad --- /dev/null +++ b/tests/std/tests/P1004R2_constexpr_vector/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\usual_latest_matrix.lst diff --git a/tests/std/tests/P1004R2_constexpr_vector/test.cpp b/tests/std/tests/P1004R2_constexpr_vector/test.cpp new file mode 100644 index 00000000000..d75d4e2045d --- /dev/null +++ b/tests/std/tests/P1004R2_constexpr_vector/test.cpp @@ -0,0 +1,638 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include +#include + +using namespace std; + +static constexpr int input[] = {0, 1, 2, 3, 4, 5}; + +template +struct soccc_allocator { + using value_type = T; + + _CONSTEXPR20_CONTAINER soccc_allocator() noexcept = default; + _CONSTEXPR20_CONTAINER explicit soccc_allocator(const int id_) noexcept : id(id_), soccc_generation(0) {} + _CONSTEXPR20_CONTAINER explicit soccc_allocator(const int id_, const int soccc_generation_) noexcept + : id(id_), soccc_generation(soccc_generation_) {} + template + _CONSTEXPR20_CONTAINER soccc_allocator(const soccc_allocator& other) noexcept + : id(other.id), soccc_generation(other.soccc_generation) {} + _CONSTEXPR20_CONTAINER soccc_allocator(const soccc_allocator& other) noexcept + : id(other.id + 1), soccc_generation(other.soccc_generation){}; + + _CONSTEXPR20_CONTAINER soccc_allocator& operator=(const soccc_allocator&) noexcept { + return *this; + } + + _CONSTEXPR20_CONTAINER soccc_allocator select_on_container_copy_construction() const noexcept { + return soccc_allocator(id, soccc_generation + 1); + } + + template + _CONSTEXPR20_CONTAINER bool operator==(const soccc_allocator& other) const noexcept { + return id == other.id; + } + + template + _CONSTEXPR20_CONTAINER bool operator!=(const soccc_allocator& other) const noexcept { + return id != other.id; + } + + _CONSTEXPR20_CONTAINER T* allocate(const size_t n) { + return allocator{}.allocate(n); + } + + _CONSTEXPR20_CONTAINER void deallocate(T* const p, const size_t n) noexcept { + allocator{}.deallocate(p, n); + } + + template + _CONSTEXPR20_CONTAINER void construct(T* const p, Args&&... args) { + construct_at(p, std::forward(args)...); + } + + int id = 0; + int soccc_generation = 0; +}; + +using vec = vector>; + +_CONSTEXPR20_CONTAINER bool test_interface() { + { // constructors + + // Non allocator constructors + vec size_default_constructed(5); + assert(size_default_constructed.size() == 5); + assert(all_of( + size_default_constructed.begin(), size_default_constructed.end(), [](const int val) { return val == 0; })); + + vec size_value_constructed(5, 7); + assert(size_value_constructed.size() == 5); + assert(all_of( + size_value_constructed.begin(), size_value_constructed.end(), [](const int val) { return val == 7; })); + + vec range_constructed(begin(input), end(input)); + assert(equal(range_constructed.begin(), range_constructed.end(), begin(input), end(input))); + + vec initializer_list_constructed({2, 3, 4, 5}); + assert(equal( + initializer_list_constructed.begin(), initializer_list_constructed.end(), begin(input) + 2, end(input))); + + // special member functions + vec default_constructed; + vec copy_constructed(size_default_constructed); + assert(equal(copy_constructed.begin(), copy_constructed.end(), size_default_constructed.begin(), + size_default_constructed.end())); + + vec move_constructed(move(copy_constructed)); + assert(equal(move_constructed.begin(), move_constructed.end(), size_default_constructed.begin(), + size_default_constructed.end())); + assert(copy_constructed.empty()); + + vec copy_assigned = range_constructed; + assert(equal(copy_assigned.begin(), copy_assigned.end(), range_constructed.begin(), range_constructed.end())); + + vec move_assigned = std::move(copy_assigned); + assert(equal(move_assigned.begin(), move_assigned.end(), range_constructed.begin(), range_constructed.end())); + assert(copy_assigned.empty()); + + // allocator constructors + soccc_allocator alloc(2, 3); + assert(alloc.id == 2); + assert(alloc.soccc_generation == 3); + + vec al_default_constructed(alloc); + assert(al_default_constructed.empty()); + assert(al_default_constructed.get_allocator().id == 4); + assert(al_default_constructed.get_allocator().soccc_generation == 3); + + vec al_copy_constructed(size_value_constructed, alloc); + assert(all_of(al_copy_constructed.begin(), al_copy_constructed.end(), [](const int val) { return val == 7; })); + assert(al_copy_constructed.get_allocator().id == 4); + assert(al_copy_constructed.get_allocator().soccc_generation == 3); + + vec al_move_constructed(move(al_copy_constructed), alloc); + assert(all_of(al_move_constructed.begin(), al_move_constructed.end(), [](const int val) { return val == 7; })); + assert(al_copy_constructed.empty()); + assert(al_move_constructed.get_allocator().id == 4); + assert(al_move_constructed.get_allocator().soccc_generation == 3); + + vec al_size_default_constructed(5, alloc); + assert(al_size_default_constructed.size() == 5); + assert(all_of(al_size_default_constructed.begin(), al_size_default_constructed.end(), + [](const int val) { return val == 0; })); + assert(al_size_default_constructed.get_allocator().id == 4); + assert(al_size_default_constructed.get_allocator().soccc_generation == 3); + + vec al_size_value_constructed(5, 7, alloc); + assert(al_size_value_constructed.size() == 5); + assert(all_of(al_size_value_constructed.begin(), al_size_value_constructed.end(), + [](const int val) { return val == 7; })); + assert(al_size_value_constructed.get_allocator().id == 4); + assert(al_size_value_constructed.get_allocator().soccc_generation == 3); + + vec al_range_constructed(begin(input), end(input), alloc); + assert(equal(al_range_constructed.begin(), al_range_constructed.end(), begin(input), end(input))); + assert(al_range_constructed.get_allocator().id == 4); + assert(al_range_constructed.get_allocator().soccc_generation == 3); + + vec al_initializer_list_constructed({2, 3, 4, 5}, alloc); + assert(equal(al_initializer_list_constructed.begin(), al_initializer_list_constructed.end(), begin(input) + 2, + end(input))); + assert(al_initializer_list_constructed.get_allocator().id == 4); + assert(al_initializer_list_constructed.get_allocator().soccc_generation == 3); + } + + { // assignment + vec range_constructed(begin(input), end(input)); + + vec copy_constructed; + copy_constructed = range_constructed; + assert(equal( + copy_constructed.begin(), copy_constructed.end(), range_constructed.begin(), range_constructed.end())); + + vec move_constructed; + move_constructed = move(copy_constructed); + assert(equal( + move_constructed.begin(), move_constructed.end(), range_constructed.begin(), range_constructed.end())); + assert(copy_constructed.empty()); + + vec initializer_list_constructed; + initializer_list_constructed = {0, 1, 2, 3, 4, 5}; + assert( + equal(initializer_list_constructed.begin(), initializer_list_constructed.end(), begin(input), end(input))); + + vec assigned; + constexpr int expected_assign_value[] = {4, 4, 4, 4, 4}; + assigned.assign(5, 4); + assert(equal(assigned.begin(), assigned.end(), begin(expected_assign_value), end(expected_assign_value))); + + assigned.assign(begin(input), end(input)); + assert(equal(assigned.begin(), assigned.end(), begin(input), end(input))); + + constexpr int expected_assign_initializer[] = {2, 3, 4, 5}; + assigned.assign({2, 3, 4, 5}); + assert(equal( + assigned.begin(), assigned.end(), begin(expected_assign_initializer), end(expected_assign_initializer))); + } + + { // allocator + vec default_constructed; + const auto alloc = default_constructed.get_allocator(); + static_assert(is_same_v, soccc_allocator>); + assert(alloc.id == 1); + assert(alloc.soccc_generation == 0); + } + + { // iterators + vec range_constructed(begin(input), end(input)); + const vec const_range_constructed(begin(input), end(input)); + + const auto b = range_constructed.begin(); + static_assert(is_same_v, vec::iterator>); + assert(*b == 0); + + const auto cb = range_constructed.cbegin(); + static_assert(is_same_v, vec::const_iterator>); + assert(*cb == 0); + + const auto cb2 = const_range_constructed.begin(); + static_assert(is_same_v, vec::const_iterator>); + assert(*cb2 == 0); + + const auto e = range_constructed.end(); + static_assert(is_same_v, vec::iterator>); + assert(*prev(e) == 5); + + const auto ce = range_constructed.cend(); + static_assert(is_same_v, vec::const_iterator>); + assert(*prev(ce) == 5); + + const auto ce2 = const_range_constructed.end(); + static_assert(is_same_v, vec::const_iterator>); + assert(*prev(ce2) == 5); + + const auto rb = range_constructed.rbegin(); + static_assert(is_same_v, reverse_iterator>); + assert(*rb == 5); + + const auto crb = range_constructed.crbegin(); + static_assert(is_same_v, reverse_iterator>); + assert(*crb == 5); + + const auto crb2 = const_range_constructed.rbegin(); + static_assert(is_same_v, reverse_iterator>); + assert(*crb2 == 5); + + const auto re = range_constructed.rend(); + static_assert(is_same_v, reverse_iterator>); + assert(*prev(re) == 0); + + const auto cre = range_constructed.crend(); + static_assert(is_same_v, reverse_iterator>); + assert(*prev(cre) == 0); + + const auto cre2 = const_range_constructed.rend(); + static_assert(is_same_v, reverse_iterator>); + assert(*prev(cre2) == 0); + } + + { // access + vec range_constructed(begin(input), end(input)); + const vec const_range_constructed(begin(input), end(input)); + + const auto at = range_constructed.at(2); + static_assert(is_same_v, int>); + assert(at == 2); + + range_constructed.at(2) = 3; + + const auto at2 = range_constructed.at(2); + static_assert(is_same_v, int>); + assert(at2 == 3); + + const auto cat = const_range_constructed.at(2); + static_assert(is_same_v, int>); + assert(cat == 2); + + const auto op = range_constructed[3]; + static_assert(is_same_v, int>); + assert(op == 3); + + range_constructed[3] = 4; + const auto op2 = range_constructed[3]; + static_assert(is_same_v, int>); + assert(op2 == 4); + + const auto cop = const_range_constructed[3]; + static_assert(is_same_v, int>); + assert(cop == 3); + + const auto f = range_constructed.front(); + static_assert(is_same_v, int>); + assert(f == 0); + + const auto cf = const_range_constructed.front(); + static_assert(is_same_v, int>); + assert(cf == 0); + + const auto b = range_constructed.back(); + static_assert(is_same_v, int>); + assert(b == 5); + + const auto cb = const_range_constructed.back(); + static_assert(is_same_v, int>); + assert(cb == 5); + + const auto d = range_constructed.data(); + static_assert(is_same_v, int*>); + assert(*d == 0); + + const auto cd = const_range_constructed.data(); + static_assert(is_same_v, const int*>); + assert(*cd == 0); + } + + { // capacity + vec range_constructed(begin(input), end(input)); + + const auto e = range_constructed.empty(); + static_assert(is_same_v, bool>); + assert(!e); + + const auto s = range_constructed.size(); + static_assert(is_same_v, std::size_t>); + assert(s == size(input)); + + const auto ms = range_constructed.max_size(); + static_assert(is_same_v, std::size_t>); + assert(ms == static_cast(-1) / 4); + + range_constructed.reserve(20); + + const auto c = range_constructed.capacity(); + static_assert(is_same_v, std::size_t>); + assert(c == 20); + + range_constructed.shrink_to_fit(); + + const auto c2 = range_constructed.capacity(); + static_assert(is_same_v, std::size_t>); + assert(c2 == 6); + } + + { // modifiers + vec range_constructed(begin(input), end(input)); + + vec cleared = range_constructed; + cleared.clear(); + assert(cleared.empty()); + assert(cleared.capacity() == range_constructed.capacity()); + + vec inserted; + + const int to_be_inserted = 3; + inserted.insert(inserted.begin(), to_be_inserted); + assert(inserted.size() == 1); + assert(inserted.front() == 3); + + const int to_be_inserted2 = 4; + inserted.insert(inserted.cbegin(), to_be_inserted2); + assert(inserted.size() == 2); + assert(inserted.front() == 4); + + inserted.insert(inserted.begin(), 1); + assert(inserted.size() == 3); + assert(inserted.front() == 1); + + inserted.insert(inserted.cbegin(), 2); + assert(inserted.size() == 4); + assert(inserted.front() == 2); + + const auto it = inserted.insert(inserted.begin(), begin(input), end(input)); + assert(inserted.size() == 10); + assert(it == inserted.begin()); + + const auto it2 = inserted.insert(inserted.cbegin(), begin(input), end(input)); + assert(inserted.size() == 16); + assert(it2 == inserted.begin()); + + const auto it3 = inserted.insert(inserted.begin(), {2, 3, 4}); + assert(inserted.size() == 19); + assert(it3 == inserted.begin()); + + inserted.insert(inserted.cbegin(), {2, 3, 4}); + assert(inserted.size() == 22); + + vec emplaced; + emplaced.emplace(emplaced.cbegin(), 42); + assert(emplaced.size() == 1); + assert(emplaced.front() == 42); + + emplaced.emplace_back(43); + assert(emplaced.size() == 2); + assert(emplaced.back() == 43); + + emplaced.push_back(44); + assert(emplaced.size() == 3); + assert(emplaced.back() == 44); + + const int to_be_pushed = 45; + emplaced.push_back(to_be_pushed); + assert(emplaced.size() == 4); + assert(emplaced.back() == 45); + + emplaced.pop_back(); + assert(emplaced.size() == 3); + assert(emplaced.back() == 44); + + emplaced.resize(1); + assert(emplaced.size() == 1); + assert(emplaced.front() == 42); + + emplaced.swap(inserted); + assert(inserted.size() == 1); + assert(inserted.front() == 42); + assert(emplaced.size() == 22); + } + + { // swap + vec first{2, 3, 4}; + vec second{5, 6, 7, 8}; + swap(first, second); + + constexpr int expected_first[] = {5, 6, 7, 8}; + constexpr int expected_second[] = {2, 3, 4}; + assert(equal(first.begin(), first.end(), begin(expected_first), end(expected_first))); + assert(equal(second.begin(), second.end(), begin(expected_second), end(expected_second))); + } + + { // erase + vec erased{1, 2, 3, 4, 2, 3, 2}; + erase(erased, 2); + constexpr int expected_erased[] = {1, 3, 4, 3}; + assert(equal(erased.begin(), erased.end(), begin(expected_erased), end(expected_erased))); + + erase_if(erased, [](const int val) { return val < 4; }); + constexpr int expected_erase_if[] = {4}; + assert(equal(erased.begin(), erased.end(), begin(expected_erase_if), end(expected_erase_if))); + } + + { // comparison + vec first(begin(input), end(input)); + vec second(begin(input), end(input)); + vec third{2, 3, 4}; + + const auto e = first == second; + static_assert(is_same_v, bool>); + assert(e); + + const auto ne = first != third; + static_assert(is_same_v, bool>); + assert(ne); + } + return true; +} + +_CONSTEXPR20_CONTAINER bool test_iterators() { + vec range_constructed(begin(input), end(input)); + + { // increment + auto it = range_constructed.begin(); + assert(*++it == 1); + assert(*it++ == 1); + assert(*it == 2); + + auto cit = range_constructed.cbegin(); + assert(*++cit == 1); + assert(*cit++ == 1); + assert(*cit == 2); + } + + { // advance + auto it = range_constructed.begin() + 2; + assert(*it == 2); + it += 2; + assert(*it == 4); + + auto cit = range_constructed.cbegin() + 2; + assert(*cit == 2); + cit += 2; + assert(*cit == 4); + } + + { // decrement + auto it = range_constructed.end(); + assert(*--it == 5); + assert(*it-- == 5); + assert(*it == 4); + + auto cit = range_constructed.cend(); + assert(*--cit == 5); + assert(*cit-- == 5); + assert(*cit == 4); + } + + { // advance back + auto it = range_constructed.end() - 2; + assert(*it == 4); + it -= 2; + assert(*it == 2); + + auto cit = range_constructed.cend() - 2; + assert(*cit == 4); + cit -= 2; + assert(*cit == 2); + } + + { // difference + const auto it1 = range_constructed.begin(); + const auto it2 = range_constructed.end(); + assert(it2 - it1 == ssize(input)); + + const auto cit1 = range_constructed.cbegin(); + const auto cit2 = range_constructed.cend(); + assert(cit2 - cit1 == ssize(input)); + + assert(it2 - cit1 == ssize(input)); + assert(cit2 - it1 == ssize(input)); + } + + { // comparison + const auto it1 = range_constructed.begin(); + const auto it2 = range_constructed.begin(); + const auto it3 = range_constructed.end(); + + assert(it1 == it2); + assert(it1 != it3); + assert(it1 < it3); + assert(it1 <= it3); + assert(it3 > it1); + assert(it3 >= it1); + } + + { // access + const auto it = range_constructed.begin() + 2; + it[2] = 3; + assert(range_constructed[4] == 3); + + const auto cit = range_constructed.cbegin() + 2; + assert(cit[2] == 3); + + std::vector> vec2 = {{1, 2}, {2, 3}}; + const auto it2 = vec2.begin(); + assert(it2->second == 2); + + const auto cit2 = vec2.cbegin(); + assert(cit2->first == 1); + } + + return true; +} + +_CONSTEXPR20_CONTAINER bool test_growth() { + { + vector v(1000, 1729); + + assert(v.size() == 1000); + assert(v.capacity() == 1000); + + v.resize(1003); + + assert(v.size() == 1003); + assert(v.capacity() == 1500); + } + + { + vector v(1000, 1729); + + assert(v.size() == 1000); + assert(v.capacity() == 1000); + + v.resize(8000); + + assert(v.size() == 8000); + assert(v.capacity() == 8000); + } + + { + vector v(1000, 1729); + + assert(v.size() == 1000); + assert(v.capacity() == 1000); + + v.push_back(47); + + assert(v.size() == 1001); + assert(v.capacity() == 1500); + } + + { + vector v(1000, 1729); + + assert(v.size() == 1000); + assert(v.capacity() == 1000); + + vector l(3, 47); + + v.insert(v.end(), l.begin(), l.end()); + + assert(v.size() == 1003); + assert(v.capacity() == 1500); + } + + { + vector v(1000, 1729); + + assert(v.size() == 1000); + assert(v.capacity() == 1000); + + vector l(7000, 47); + + v.insert(v.end(), l.begin(), l.end()); + + assert(v.size() == 8000); + assert(v.capacity() == 8000); + } + + { + vector v(1000, 1729); + + assert(v.size() == 1000); + assert(v.capacity() == 1000); + + v.insert(v.end(), 3, 47); + + assert(v.size() == 1003); + assert(v.capacity() == 1500); + } + + { + vector v(1000, 1729); + + assert(v.size() == 1000); + assert(v.capacity() == 1000); + + v.insert(v.end(), 7000, 47); + + assert(v.size() == 8000); + assert(v.capacity() == 8000); + } + return true; +} + +int main() { + test_interface(); + test_iterators(); + test_growth(); +#ifdef __cpp_lib_constexpr_vector + static_assert(test_interface()); + static_assert(test_iterators()); + static_assert(test_growth()); +#endif // __cpp_lib_constexpr_vector +} diff --git a/tests/std/tests/P1004R2_constexpr_vector_bool/env.lst b/tests/std/tests/P1004R2_constexpr_vector_bool/env.lst new file mode 100644 index 00000000000..642f530ffad --- /dev/null +++ b/tests/std/tests/P1004R2_constexpr_vector_bool/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\usual_latest_matrix.lst diff --git a/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp b/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp new file mode 100644 index 00000000000..c13ba554c0c --- /dev/null +++ b/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp @@ -0,0 +1,538 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include +#include + +using namespace std; + +static constexpr bool input[] = {true, false, true, true, false, true}; + +template +struct soccc_allocator { + using value_type = T; + + _CONSTEXPR20_DYNALLOC soccc_allocator() noexcept = default; + _CONSTEXPR20_DYNALLOC explicit soccc_allocator(const int id_) noexcept : id(id_), soccc_generation(0) {} + _CONSTEXPR20_DYNALLOC explicit soccc_allocator(const int id_, const int soccc_generation_) noexcept + : id(id_), soccc_generation(soccc_generation_) {} + template + _CONSTEXPR20_DYNALLOC soccc_allocator(const soccc_allocator& other) noexcept + : id(other.id), soccc_generation(other.soccc_generation) {} + _CONSTEXPR20_DYNALLOC soccc_allocator(const soccc_allocator& other) noexcept + : id(other.id + 1), soccc_generation(other.soccc_generation){}; + + _CONSTEXPR20_DYNALLOC soccc_allocator& operator=(const soccc_allocator&) noexcept { + return *this; + } + + _CONSTEXPR20_DYNALLOC soccc_allocator select_on_container_copy_construction() const noexcept { + return soccc_allocator(id, soccc_generation + 1); + } + + template + _CONSTEXPR20_DYNALLOC bool operator==(const soccc_allocator& other) const noexcept { + return id == other.id; + } + + template + _CONSTEXPR20_DYNALLOC bool operator!=(const soccc_allocator& other) const noexcept { + return id != other.id; + } + + _CONSTEXPR20_DYNALLOC T* allocate(const size_t n) { + return allocator{}.allocate(n); + } + + _CONSTEXPR20_DYNALLOC void deallocate(T* const p, const size_t n) noexcept { + allocator{}.deallocate(p, n); + } + + template + _CONSTEXPR20_DYNALLOC void construct(T* const p, Args&&... args) { + construct_at(p, std::forward(args)...); + } + + int id = 0; + int soccc_generation = 0; +}; + +using vec = vector>; + +_CONSTEXPR20_DYNALLOC bool test_interface() { + { // constructors + + // Non allocator constructors + vec size_default_constructed(5); + assert(size_default_constructed.size() == 5); + assert(all_of( + size_default_constructed.begin(), size_default_constructed.end(), [](const bool val) { return !val; })); + + vec size_value_constructed(5, true); + assert(size_value_constructed.size() == 5); + assert( + all_of(size_value_constructed.begin(), size_value_constructed.end(), [](const bool val) { return val; })); + + vec range_constructed(begin(input), end(input)); + assert(equal(range_constructed.begin(), range_constructed.end(), begin(input), end(input))); + + vec initializer_list_constructed({true, true, false, true}); + assert(equal( + initializer_list_constructed.begin(), initializer_list_constructed.end(), begin(input) + 2, end(input))); + + // special member functions + vec default_constructed; + vec copy_constructed(size_default_constructed); + assert(equal(copy_constructed.begin(), copy_constructed.end(), size_default_constructed.begin(), + size_default_constructed.end())); + + vec move_constructed(move(copy_constructed)); + assert(equal(move_constructed.begin(), move_constructed.end(), size_default_constructed.begin(), + size_default_constructed.end())); + assert(copy_constructed.empty()); + + vec copy_assigned = range_constructed; + assert(equal(copy_assigned.begin(), copy_assigned.end(), range_constructed.begin(), range_constructed.end())); + + vec move_assigned = std::move(copy_assigned); + assert(equal(move_assigned.begin(), move_assigned.end(), range_constructed.begin(), range_constructed.end())); + assert(copy_assigned.empty()); + + // allocator constructors + soccc_allocator alloc(2, 3); + assert(alloc.id == 2); + assert(alloc.soccc_generation == 3); + + vec al_default_constructed(alloc); + assert(al_default_constructed.empty()); + assert(al_default_constructed.get_allocator().id == 4); + assert(al_default_constructed.get_allocator().soccc_generation == 3); + + vec al_copy_constructed(size_value_constructed, alloc); + assert(all_of(al_copy_constructed.begin(), al_copy_constructed.end(), [](const bool val) { return val; })); + assert(al_copy_constructed.get_allocator().id == 4); + assert(al_copy_constructed.get_allocator().soccc_generation == 3); + + vec al_move_constructed(move(al_copy_constructed), alloc); + assert(all_of(al_move_constructed.begin(), al_move_constructed.end(), [](const bool val) { return val; })); + assert(al_copy_constructed.empty()); + assert(al_move_constructed.get_allocator().id == 4); + assert(al_move_constructed.get_allocator().soccc_generation == 3); + + vec al_size_default_constructed(5, alloc); + assert(al_size_default_constructed.size() == 5); + assert(all_of(al_size_default_constructed.begin(), al_size_default_constructed.end(), + [](const bool val) { return !val; })); + assert(al_size_default_constructed.get_allocator().id == 4); + assert(al_size_default_constructed.get_allocator().soccc_generation == 3); + + vec al_size_value_constructed(5, true, alloc); + assert(al_size_value_constructed.size() == 5); + assert(all_of( + al_size_value_constructed.begin(), al_size_value_constructed.end(), [](const bool val) { return val; })); + assert(al_size_value_constructed.get_allocator().id == 4); + assert(al_size_value_constructed.get_allocator().soccc_generation == 3); + + vec al_range_constructed(begin(input), end(input), alloc); + assert(equal(al_range_constructed.begin(), al_range_constructed.end(), begin(input), end(input))); + assert(al_range_constructed.get_allocator().id == 4); + assert(al_range_constructed.get_allocator().soccc_generation == 3); + + vec al_initializer_list_constructed({true, true, false, true}, alloc); + assert(equal(al_initializer_list_constructed.begin(), al_initializer_list_constructed.end(), begin(input) + 2, + end(input))); + assert(al_initializer_list_constructed.get_allocator().id == 4); + assert(al_initializer_list_constructed.get_allocator().soccc_generation == 3); + } + + { // assignment + vec range_constructed(begin(input), end(input)); + + vec copy_constructed; + copy_constructed = range_constructed; + assert(equal( + copy_constructed.begin(), copy_constructed.end(), range_constructed.begin(), range_constructed.end())); + + vec move_constructed; + move_constructed = move(copy_constructed); + assert(equal( + move_constructed.begin(), move_constructed.end(), range_constructed.begin(), range_constructed.end())); + assert(copy_constructed.empty()); + + vec initializer_list_constructed; + initializer_list_constructed = {true, false, true, true, false, true}; + assert( + equal(initializer_list_constructed.begin(), initializer_list_constructed.end(), begin(input), end(input))); + + vec assigned; + constexpr bool expected_assign_value[] = {true, true, true, true, true}; + assigned.assign(5, true); + assert(equal(assigned.begin(), assigned.end(), begin(expected_assign_value), end(expected_assign_value))); + + assigned.assign(begin(input), end(input)); + assert(equal(assigned.begin(), assigned.end(), begin(input), end(input))); + + constexpr bool expected_assign_initializer[] = {true, false, true, true, false, true}; + assigned.assign({true, false, true, true, false, true}); + assert(equal( + assigned.begin(), assigned.end(), begin(expected_assign_initializer), end(expected_assign_initializer))); + } + + { // allocator + vec default_constructed; + const auto alloc = default_constructed.get_allocator(); + static_assert(is_same_v, soccc_allocator>); + assert(alloc.id == 1); + assert(alloc.soccc_generation == 0); + } + + { // iterators + vec range_constructed(begin(input), end(input)); + const vec const_range_constructed(begin(input), end(input)); + + const auto b = range_constructed.begin(); + static_assert(is_same_v, vec::iterator>); + assert(*b); + + const auto cb = range_constructed.cbegin(); + static_assert(is_same_v, vec::const_iterator>); + assert(*cb); + + const auto cb2 = const_range_constructed.begin(); + static_assert(is_same_v, vec::const_iterator>); + assert(*cb2); + + const auto e = range_constructed.end(); + static_assert(is_same_v, vec::iterator>); + assert(*prev(e)); + + const auto ce = range_constructed.cend(); + static_assert(is_same_v, vec::const_iterator>); + assert(*prev(ce)); + + const auto ce2 = const_range_constructed.end(); + static_assert(is_same_v, vec::const_iterator>); + assert(*prev(ce2)); + + const auto rb = range_constructed.rbegin(); + static_assert(is_same_v, reverse_iterator>); + assert(*rb); + + const auto crb = range_constructed.crbegin(); + static_assert(is_same_v, reverse_iterator>); + assert(*crb); + + const auto crb2 = const_range_constructed.rbegin(); + static_assert(is_same_v, reverse_iterator>); + assert(*crb2); + + const auto re = range_constructed.rend(); + static_assert(is_same_v, reverse_iterator>); + assert(*prev(re)); + + const auto cre = range_constructed.crend(); + static_assert(is_same_v, reverse_iterator>); + assert(*prev(cre)); + + const auto cre2 = const_range_constructed.rend(); + static_assert(is_same_v, reverse_iterator>); + assert(*prev(cre2)); + } + + { // access + vec range_constructed(begin(input), end(input)); + const vec const_range_constructed(begin(input), end(input)); + + const auto at = range_constructed.at(2); + static_assert(is_same_v, _Iter_ref_t>); + assert(at); + + range_constructed.at(2) = false; + + const auto at2 = range_constructed.at(2); + static_assert(is_same_v, _Iter_ref_t>); + assert(at2 == false); + + const auto cat = const_range_constructed.at(2); + static_assert(is_same_v, _Iter_ref_t>); + assert(cat); + + const auto op = range_constructed[3]; + static_assert(is_same_v, _Iter_ref_t>); + assert(op); + + range_constructed[3] = true; + const auto op2 = range_constructed[3]; + static_assert(is_same_v, _Iter_ref_t>); + assert(op2); + + const auto cop = const_range_constructed[3]; + static_assert(is_same_v, _Iter_ref_t>); + assert(cop); + + const auto f = range_constructed.front(); + static_assert(is_same_v, _Iter_ref_t>); + assert(f); + + const auto cf = const_range_constructed.front(); + static_assert(is_same_v, _Iter_ref_t>); + assert(cf); + + const auto b = range_constructed.back(); + static_assert(is_same_v, _Iter_ref_t>); + assert(b); + + const auto cb = const_range_constructed.back(); + static_assert(is_same_v, _Iter_ref_t>); + assert(cb); + } + + { // capacity + vec range_constructed(begin(input), end(input)); + + const auto e = range_constructed.empty(); + static_assert(is_same_v, bool>); + assert(e == false); + + const auto s = range_constructed.size(); + static_assert(is_same_v, std::size_t>); + assert(s == size(input)); + + const auto ms = range_constructed.max_size(); + static_assert(is_same_v, std::size_t>); + assert(ms == static_cast(std::numeric_limits::max())); + + range_constructed.reserve(20); + + const auto c = range_constructed.capacity(); + static_assert(is_same_v, std::size_t>); + assert(c == 32); + + range_constructed.shrink_to_fit(); + + const auto c2 = range_constructed.capacity(); + static_assert(is_same_v, std::size_t>); + assert(c2 == 32); + } + + { // modifiers + vec range_constructed(begin(input), end(input)); + + vec cleared = range_constructed; + cleared.clear(); + assert(cleared.empty()); + assert(cleared.capacity() == range_constructed.capacity()); + + vec inserted; + + const bool to_be_inserted = true; + inserted.insert(inserted.begin(), to_be_inserted); + assert(inserted.size() == 1); + assert(inserted.front()); + + const bool to_be_inserted2 = false; + inserted.insert(inserted.cbegin(), to_be_inserted2); + assert(inserted.size() == 2); + assert(inserted.front() == false); + + inserted.insert(inserted.begin(), true); + assert(inserted.size() == 3); + assert(inserted.front()); + + inserted.insert(inserted.cbegin(), false); + assert(inserted.size() == 4); + assert(inserted.front() == false); + + const auto it = inserted.insert(inserted.begin(), begin(input), end(input)); + assert(inserted.size() == 10); + assert(it == inserted.begin()); + + const auto it2 = inserted.insert(inserted.cbegin(), begin(input), end(input)); + assert(inserted.size() == 16); + assert(it2 == inserted.begin()); + + const auto it3 = inserted.insert(inserted.begin(), {true, false, true}); + assert(inserted.size() == 19); + assert(it3 == inserted.begin()); + + inserted.insert(inserted.cbegin(), {false, true, false}); + assert(inserted.size() == 22); + + vec emplaced; + emplaced.emplace(emplaced.cbegin(), false); + assert(emplaced.size() == 1); + assert(emplaced.front() == false); + + emplaced.emplace_back(true); + assert(emplaced.size() == 2); + assert(emplaced.back()); + + emplaced.push_back(false); + assert(emplaced.size() == 3); + assert(emplaced.back() == false); + + const bool to_be_pushed = true; + emplaced.push_back(to_be_pushed); + assert(emplaced.size() == 4); + assert(emplaced.back()); + + emplaced.pop_back(); + assert(emplaced.size() == 3); + assert(emplaced.back() == false); + + emplaced.resize(1); + assert(emplaced.size() == 1); + assert(emplaced.front() == false); + + emplaced.swap(inserted); + assert(inserted.size() == 1); + assert(inserted.front() == false); + assert(emplaced.size() == 22); + } + + { // swap + vec first{true, false, true}; + vec second{false, false, true, false}; + swap(first, second); + + constexpr bool expected_first[] = {false, false, true, false}; + constexpr bool expected_second[] = {true, false, true}; + assert(equal(first.begin(), first.end(), begin(expected_first), end(expected_first))); + assert(equal(second.begin(), second.end(), begin(expected_second), end(expected_second))); + } + + { // erase + vec erased{false, false, true, false, true}; + erase(erased, false); + constexpr bool expected_erased[] = {true, true}; + assert(equal(erased.begin(), erased.end(), begin(expected_erased), end(expected_erased))); + + vec erased_if{false, false, true, false, true}; + erase_if(erased_if, [](const bool val) { return val; }); + constexpr bool expected_erase_if[] = {false, false, false}; + assert(equal(erased_if.begin(), erased_if.end(), begin(expected_erase_if), end(expected_erase_if))); + } + + { // comparison + vec first(begin(input), end(input)); + vec second(begin(input), end(input)); + vec third{true, false, true}; + + const auto e = first == second; + static_assert(is_same_v, bool>); + assert(e); + + const auto ne = first != third; + static_assert(is_same_v, bool>); + assert(ne); + } + return true; +} + +_CONSTEXPR20_DYNALLOC bool test_iterators() { + vec range_constructed(begin(input), end(input)); + + { // increment + auto it = range_constructed.begin(); + assert(*++it == false); + assert(*it++ == false); + assert(*it); + + auto cit = range_constructed.cbegin(); + assert(*++cit == false); + assert(*cit++ == false); + assert(*cit); + } + + { // advance + auto it = range_constructed.begin() + 2; + assert(*it); + it += 2; + assert(*it == false); + + auto cit = range_constructed.cbegin() + 2; + assert(*cit); + cit += 2; + assert(*cit == false); + } + + { // decrement + auto it = range_constructed.end(); + assert(*--it); + assert(*it--); + assert(*it == false); + + auto cit = range_constructed.cend(); + assert(*--cit); + assert(*cit--); + assert(*cit == false); + } + + { // advance back + auto it = range_constructed.end() - 2; + assert(*it == false); + it -= 2; + assert(*it); + + auto cit = range_constructed.cend() - 2; + assert(*cit == false); + cit -= 2; + assert(*cit); + } + + { // difference + const auto it1 = range_constructed.begin(); + const auto it2 = range_constructed.end(); + assert(it2 - it1 == ssize(input)); + + const auto cit1 = range_constructed.cbegin(); + const auto cit2 = range_constructed.cend(); + assert(cit2 - cit1 == ssize(input)); + + assert(it2 - cit1 == ssize(input)); + assert(cit2 - it1 == ssize(input)); + } + + { // comparison + const auto it1 = range_constructed.begin(); + const auto it2 = range_constructed.begin(); + const auto it3 = range_constructed.end(); + + assert(it1 == it2); + assert(it1 != it3); + assert(it1 < it3); + assert(it1 <= it3); + assert(it3 > it1); + assert(it3 >= it1); + } + + { // access + const auto it = range_constructed.begin() + 2; + it[2] = false; + assert(range_constructed[4] == false); + + const auto cit = range_constructed.cbegin() + 2; + assert(cit[2] == false); + + std::vector> vec2 = {{false, true}, {true, false}}; + const auto it2 = vec2.begin(); + assert(it2->second); + + const auto cit2 = vec2.cbegin(); + assert(cit2->first == false); + } + + return true; +} + +int main() { + test_interface(); + test_iterators(); +#ifdef __cpp_lib_constexpr_vector + static_assert(test_interface()); + static_assert(test_iterators()); +#endif // __cpp_lib_constexpr_vector +} From c3690908d53d7f28f4a78eaf81679c58e371e9b5 Mon Sep 17 00:00:00 2001 From: Michael Schellenberger Costa Date: Fri, 29 Jan 2021 12:31:06 +0100 Subject: [PATCH 12/50] Properly unlock everytime --- stl/inc/vector | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/stl/inc/vector b/stl/inc/vector index 5fe858a6897..d919e8311a7 100644 --- a/stl/inc/vector +++ b/stl/inc/vector @@ -1447,10 +1447,10 @@ public: #endif // __cpp_lib_constexpr_dynamic_alloc { _STL_VERIFY(_My_data._Myfirst != _Mylast, "vector empty before pop"); - _Orphan_range(_Mylast - 1, _Mylast); } #endif // _ITERATOR_DEBUG_LEVEL == 2 + _Orphan_range(_Mylast - 1, _Mylast); _Alty_traits::destroy(_Getal(), _Unfancy(_Mylast - 1)); --_Mylast; } @@ -1469,10 +1469,10 @@ public: _STL_VERIFY( _Where._Getcont() == _STD addressof(_My_data) && _Whereptr >= _My_data._Myfirst && _Mylast > _Whereptr, "vector erase iterator outside range"); - _Orphan_range(_Whereptr, _Mylast); } #endif // _ITERATOR_DEBUG_LEVEL == 2 + _Orphan_range(_Whereptr, _Mylast); _Move_unchecked(_Whereptr + 1, _Mylast, _Whereptr); _Alty_traits::destroy(_Getal(), _Unfancy(_Mylast - 1)); --_Mylast; @@ -1871,8 +1871,7 @@ private: } #if _ITERATOR_DEBUG_LEVEL == 2 - void _Orphan_range_locked(pointer _First, pointer _Last) const { - _Lockit _Lock(_LOCK_DEBUG); + _CONSTEXPR20_CONTAINER void _Orphan_range_unlocked(pointer _First, pointer _Last) const { _Iterator_base12** _Pnext = &_Mypair._Myval2._Myproxy->_Myfirstiter; while (*_Pnext) { const auto _Pnextptr = static_cast(**_Pnext)._Ptr; @@ -1885,9 +1884,16 @@ private: } } + void _Orphan_range_locked(pointer _First, pointer _Last) const { + _Lockit _Lock(_LOCK_DEBUG); + _Orphan_range_unlocked(_First, _Last); + } + _CONSTEXPR20_CONTAINER void _Orphan_range(pointer _First, pointer _Last) const { #ifdef __cpp_lib_constexpr_dynamic_alloc - if (!_STD is_constant_evaluated()) + if (_STD is_constant_evaluated()) { + _Orphan_range_unlocked(_First, _Last); + } else #endif // __cpp_lib_constexpr_dynamic_alloc { _Orphan_range_locked(_First, _Last); @@ -3013,8 +3019,7 @@ public: } #if _ITERATOR_DEBUG_LEVEL == 2 - void _Orphan_range_locked(size_type _Offlo, size_type _Offhi) const { - _Lockit _Lock(_LOCK_DEBUG); + _CONSTEXPR20_CONTAINER void _Orphan_range_unlocked(size_type _Offlo, size_type _Offhi) const { const auto _Base = this->_Myvec.data(); _Iterator_base12** _Pnext = &this->_Myproxy->_Myfirstiter; @@ -3030,9 +3035,16 @@ public: } } + void _Orphan_range_locked(size_type _Offlo, size_type _Offhi) const { + _Lockit _Lock(_LOCK_DEBUG); + _Orphan_range_unlocked(_Offlo, _Offhi); + } + _CONSTEXPR20_CONTAINER void _Orphan_range(size_type _Offlo, size_type _Offhi) const { #ifdef __cpp_lib_constexpr_dynamic_alloc - if (!_STD is_constant_evaluated()) + if (!_STD is_constant_evaluated()) { + _Orphan_range_unlocked(_Offlo, _Offhi); + } else #endif // __cpp_lib_constexpr_dynamic_alloc { _Orphan_range_locked(_Offlo, _Offhi); From c0d079bd0557569db386defb17749b605d090d70 Mon Sep 17 00:00:00 2001 From: Michael Schellenberger Costa Date: Fri, 29 Jan 2021 20:18:56 +0100 Subject: [PATCH 13/50] Another forgotten proxy validation --- stl/inc/vector | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/stl/inc/vector b/stl/inc/vector index d919e8311a7..e29e1d9a07d 100644 --- a/stl/inc/vector +++ b/stl/inc/vector @@ -1375,7 +1375,10 @@ private: _CONSTEXPR20_CONTAINER void _Check_all_orphaned() const noexcept { #ifdef __cpp_lib_constexpr_dynamic_alloc - if (!_STD is_constant_evaluated()) + if (_STD is_constant_evaluated()) { + auto& _My_data = _Mypair._Myval2; + _STL_INTERNAL_CHECK(!_My_data._Myproxy->_Myfirstiter); + } else #endif // __cpp_lib_constexpr_dynamic_alloc { _Check_all_orphaned_locked(); From 1c9b289257fbf9a5635ea91ed3c83ada5c30af5c Mon Sep 17 00:00:00 2001 From: Michael Schellenberger Costa Date: Fri, 29 Jan 2021 20:20:40 +0100 Subject: [PATCH 14/50] Negation is hard --- stl/inc/vector | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/vector b/stl/inc/vector index e29e1d9a07d..fd29ca88265 100644 --- a/stl/inc/vector +++ b/stl/inc/vector @@ -3045,7 +3045,7 @@ public: _CONSTEXPR20_CONTAINER void _Orphan_range(size_type _Offlo, size_type _Offhi) const { #ifdef __cpp_lib_constexpr_dynamic_alloc - if (!_STD is_constant_evaluated()) { + if (_STD is_constant_evaluated()) { _Orphan_range_unlocked(_Offlo, _Offhi); } else #endif // __cpp_lib_constexpr_dynamic_alloc From fd7c40208fc039c6c85964bd66f48570fd033365 Mon Sep 17 00:00:00 2001 From: Miya Natsuhara Date: Wed, 3 Feb 2021 17:04:26 -0800 Subject: [PATCH 15/50] Disable portions of P1004R2_constexpr_vector test for EDG and C1XX bugs --- .../tests/P1004R2_constexpr_vector/test.cpp | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/tests/std/tests/P1004R2_constexpr_vector/test.cpp b/tests/std/tests/P1004R2_constexpr_vector/test.cpp index d75d4e2045d..40ef1e37a7c 100644 --- a/tests/std/tests/P1004R2_constexpr_vector/test.cpp +++ b/tests/std/tests/P1004R2_constexpr_vector/test.cpp @@ -9,7 +9,9 @@ using namespace std; +#if defined(MSVC_INTERNAL_TESTING) || defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1270433 static constexpr int input[] = {0, 1, 2, 3, 4, 5}; +#endif // defined(MSVC_INTERNAL_TESTING) || defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 template struct soccc_allocator { @@ -63,42 +65,60 @@ struct soccc_allocator { using vec = vector>; _CONSTEXPR20_CONTAINER bool test_interface() { +#if defined(MSVC_INTERNAL_TESTING) || defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1270433 { // constructors // Non allocator constructors vec size_default_constructed(5); assert(size_default_constructed.size() == 5); +#ifndef __EDG__ // TRANSITION, VSO-1273296 assert(all_of( size_default_constructed.begin(), size_default_constructed.end(), [](const int val) { return val == 0; })); +#endif // __EDG__ vec size_value_constructed(5, 7); assert(size_value_constructed.size() == 5); +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273365 assert(all_of( size_value_constructed.begin(), size_value_constructed.end(), [](const int val) { return val == 7; })); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 vec range_constructed(begin(input), end(input)); +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1274387 assert(equal(range_constructed.begin(), range_constructed.end(), begin(input), end(input))); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 vec initializer_list_constructed({2, 3, 4, 5}); +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1274387 assert(equal( initializer_list_constructed.begin(), initializer_list_constructed.end(), begin(input) + 2, end(input))); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // special member functions vec default_constructed; vec copy_constructed(size_default_constructed); +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1274387 assert(equal(copy_constructed.begin(), copy_constructed.end(), size_default_constructed.begin(), size_default_constructed.end())); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 vec move_constructed(move(copy_constructed)); +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1274387 assert(equal(move_constructed.begin(), move_constructed.end(), size_default_constructed.begin(), size_default_constructed.end())); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 + assert(copy_constructed.empty()); vec copy_assigned = range_constructed; +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1274387 assert(equal(copy_assigned.begin(), copy_assigned.end(), range_constructed.begin(), range_constructed.end())); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 vec move_assigned = std::move(copy_assigned); +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1274387 assert(equal(move_assigned.begin(), move_assigned.end(), range_constructed.begin(), range_constructed.end())); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 assert(copy_assigned.empty()); // allocator constructors @@ -112,42 +132,55 @@ _CONSTEXPR20_CONTAINER bool test_interface() { assert(al_default_constructed.get_allocator().soccc_generation == 3); vec al_copy_constructed(size_value_constructed, alloc); +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273365 assert(all_of(al_copy_constructed.begin(), al_copy_constructed.end(), [](const int val) { return val == 7; })); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 assert(al_copy_constructed.get_allocator().id == 4); assert(al_copy_constructed.get_allocator().soccc_generation == 3); vec al_move_constructed(move(al_copy_constructed), alloc); +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273365 assert(all_of(al_move_constructed.begin(), al_move_constructed.end(), [](const int val) { return val == 7; })); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 assert(al_copy_constructed.empty()); assert(al_move_constructed.get_allocator().id == 4); assert(al_move_constructed.get_allocator().soccc_generation == 3); vec al_size_default_constructed(5, alloc); assert(al_size_default_constructed.size() == 5); +#ifndef __EDG__ // TRANSITION, VSO-1273296 assert(all_of(al_size_default_constructed.begin(), al_size_default_constructed.end(), [](const int val) { return val == 0; })); +#endif // __EDG__ assert(al_size_default_constructed.get_allocator().id == 4); assert(al_size_default_constructed.get_allocator().soccc_generation == 3); vec al_size_value_constructed(5, 7, alloc); assert(al_size_value_constructed.size() == 5); +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273365 assert(all_of(al_size_value_constructed.begin(), al_size_value_constructed.end(), [](const int val) { return val == 7; })); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 assert(al_size_value_constructed.get_allocator().id == 4); assert(al_size_value_constructed.get_allocator().soccc_generation == 3); vec al_range_constructed(begin(input), end(input), alloc); +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1274387 assert(equal(al_range_constructed.begin(), al_range_constructed.end(), begin(input), end(input))); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 assert(al_range_constructed.get_allocator().id == 4); assert(al_range_constructed.get_allocator().soccc_generation == 3); vec al_initializer_list_constructed({2, 3, 4, 5}, alloc); +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1274387 assert(equal(al_initializer_list_constructed.begin(), al_initializer_list_constructed.end(), begin(input) + 2, end(input))); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 assert(al_initializer_list_constructed.get_allocator().id == 4); assert(al_initializer_list_constructed.get_allocator().soccc_generation == 3); } +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1274387 { // assignment vec range_constructed(begin(input), end(input)); @@ -180,6 +213,7 @@ _CONSTEXPR20_CONTAINER bool test_interface() { assert(equal( assigned.begin(), assigned.end(), begin(expected_assign_initializer), end(expected_assign_initializer))); } +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 { // allocator vec default_constructed; @@ -193,6 +227,7 @@ _CONSTEXPR20_CONTAINER bool test_interface() { vec range_constructed(begin(input), end(input)); const vec const_range_constructed(begin(input), end(input)); +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273381 const auto b = range_constructed.begin(); static_assert(is_same_v, vec::iterator>); assert(*b == 0); @@ -240,6 +275,7 @@ _CONSTEXPR20_CONTAINER bool test_interface() { const auto cre2 = const_range_constructed.rend(); static_assert(is_same_v, reverse_iterator>); assert(*prev(cre2) == 0); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 } { // access @@ -336,6 +372,7 @@ _CONSTEXPR20_CONTAINER bool test_interface() { vec inserted; +#ifndef __EDG__ // TRANSITION, VSO-1273386, VSO-1274387 const int to_be_inserted = 3; inserted.insert(inserted.begin(), to_be_inserted); assert(inserted.size() == 1); @@ -353,7 +390,9 @@ _CONSTEXPR20_CONTAINER bool test_interface() { inserted.insert(inserted.cbegin(), 2); assert(inserted.size() == 4); assert(inserted.front() == 2); +#endif // __EDG__ +#ifndef __EDG__ // TRANSITION, VSO-1273381, VSO-1273296 const auto it = inserted.insert(inserted.begin(), begin(input), end(input)); assert(inserted.size() == 10); assert(it == inserted.begin()); @@ -365,7 +404,9 @@ _CONSTEXPR20_CONTAINER bool test_interface() { const auto it3 = inserted.insert(inserted.begin(), {2, 3, 4}); assert(inserted.size() == 19); assert(it3 == inserted.begin()); +#endif // __EDG__ +#ifndef __EDG__ // TRANSITION, VSO-1274387, VSO-1273296 inserted.insert(inserted.cbegin(), {2, 3, 4}); assert(inserted.size() == 22); @@ -399,8 +440,10 @@ _CONSTEXPR20_CONTAINER bool test_interface() { assert(inserted.size() == 1); assert(inserted.front() == 42); assert(emplaced.size() == 22); +#endif // __EDG__ } +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273365 { // swap vec first{2, 3, 4}; vec second{5, 6, 7, 8}; @@ -411,7 +454,9 @@ _CONSTEXPR20_CONTAINER bool test_interface() { assert(equal(first.begin(), first.end(), begin(expected_first), end(expected_first))); assert(equal(second.begin(), second.end(), begin(expected_second), end(expected_second))); } +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273365 { // erase vec erased{1, 2, 3, 4, 2, 3, 2}; erase(erased, 2); @@ -422,6 +467,7 @@ _CONSTEXPR20_CONTAINER bool test_interface() { constexpr int expected_erase_if[] = {4}; assert(equal(erased.begin(), erased.end(), begin(expected_erase_if), end(expected_erase_if))); } +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 { // comparison vec first(begin(input), end(input)); @@ -436,12 +482,15 @@ _CONSTEXPR20_CONTAINER bool test_interface() { static_assert(is_same_v, bool>); assert(ne); } +#endif // defined(MSVC_INTERNAL_TESTING) || defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 return true; } _CONSTEXPR20_CONTAINER bool test_iterators() { +#if defined(MSVC_INTERNAL_TESTING) || defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1270433 vec range_constructed(begin(input), end(input)); +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273381 { // increment auto it = range_constructed.begin(); assert(*++it == 1); @@ -532,10 +581,13 @@ _CONSTEXPR20_CONTAINER bool test_iterators() { assert(cit2->first == 1); } +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 +#endif // defined(MSVC_INTERNAL_TESTING) || defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 return true; } _CONSTEXPR20_CONTAINER bool test_growth() { +#if defined(MSVC_INTERNAL_TESTING) || defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1270433 { vector v(1000, 1729); @@ -580,10 +632,12 @@ _CONSTEXPR20_CONTAINER bool test_growth() { vector l(3, 47); +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1274387 v.insert(v.end(), l.begin(), l.end()); assert(v.size() == 1003); assert(v.capacity() == 1500); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 } { @@ -594,10 +648,12 @@ _CONSTEXPR20_CONTAINER bool test_growth() { vector l(7000, 47); +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1274387 v.insert(v.end(), l.begin(), l.end()); assert(v.size() == 8000); assert(v.capacity() == 8000); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 } { @@ -606,10 +662,12 @@ _CONSTEXPR20_CONTAINER bool test_growth() { assert(v.size() == 1000); assert(v.capacity() == 1000); +#ifndef __EDG__ // TRANSITION, VSO-1273386, VSO-1274387 v.insert(v.end(), 3, 47); assert(v.size() == 1003); assert(v.capacity() == 1500); +#endif // __EDG__ } { @@ -618,11 +676,14 @@ _CONSTEXPR20_CONTAINER bool test_growth() { assert(v.size() == 1000); assert(v.capacity() == 1000); +#ifndef __EDG__ // TRANSITION, VSO-1273386, VSO-1274387 v.insert(v.end(), 7000, 47); assert(v.size() == 8000); assert(v.capacity() == 8000); +#endif // __EDG__ } +#endif // defined(MSVC_INTERNAL_CHECKING) || defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 return true; } From 649724fc14bbc5dd2132dc6b720ceae60c8cfb4d Mon Sep 17 00:00:00 2001 From: Miya Natsuhara Date: Wed, 3 Feb 2021 17:22:59 -0800 Subject: [PATCH 16/50] update test functions with new _CONSTEXPR20_CONTAINER macro --- tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp b/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp index c13ba554c0c..675d28a148f 100644 --- a/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp +++ b/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp @@ -62,7 +62,7 @@ struct soccc_allocator { using vec = vector>; -_CONSTEXPR20_DYNALLOC bool test_interface() { +_CONSTEXPR20_CONTAINER bool test_interface() { { // constructors // Non allocator constructors @@ -432,7 +432,7 @@ _CONSTEXPR20_DYNALLOC bool test_interface() { return true; } -_CONSTEXPR20_DYNALLOC bool test_iterators() { +_CONSTEXPR20_CONTAINER bool test_iterators() { vec range_constructed(begin(input), end(input)); { // increment From 6a93a12b7db67fae3d5ce3286c777d7125088ca3 Mon Sep 17 00:00:00 2001 From: Miya Natsuhara Date: Thu, 4 Feb 2021 17:13:14 -0800 Subject: [PATCH 17/50] #if out appropriate regions of vector bool test for EDG/cl bugs --- .../P1004R2_constexpr_vector_bool/test.cpp | 75 ++++++++++++++++++- 1 file changed, 74 insertions(+), 1 deletion(-) diff --git a/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp b/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp index 675d28a148f..de660537442 100644 --- a/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp +++ b/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp @@ -9,7 +9,9 @@ using namespace std; +#if defined(MSVC_INTERNAL_TESTING) || defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1270433 static constexpr bool input[] = {true, false, true, true, false, true}; +#endif // defined(MSVC_INTERNAL_TESTING) || defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 template struct soccc_allocator { @@ -63,92 +65,132 @@ struct soccc_allocator { using vec = vector>; _CONSTEXPR20_CONTAINER bool test_interface() { +#if defined(MSVC_INTERNAL_TESTING) || defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1270433 { // constructors - // Non allocator constructors +// Non allocator constructors +#ifndef __EDG__ // TRANSITION, VSO-1274387 vec size_default_constructed(5); assert(size_default_constructed.size() == 5); +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273296 assert(all_of( size_default_constructed.begin(), size_default_constructed.end(), [](const bool val) { return !val; })); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL ! =2 +#endif // __EDG__ +#ifndef __EDG__ // TRANSITION, VSO-1274387 vec size_value_constructed(5, true); assert(size_value_constructed.size() == 5); +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273296 assert( all_of(size_value_constructed.begin(), size_value_constructed.end(), [](const bool val) { return val; })); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 +#endif // __EDG__ +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273365 +#ifndef __EDG__ // TRANSITION, VSO-1274387 vec range_constructed(begin(input), end(input)); assert(equal(range_constructed.begin(), range_constructed.end(), begin(input), end(input))); vec initializer_list_constructed({true, true, false, true}); assert(equal( initializer_list_constructed.begin(), initializer_list_constructed.end(), begin(input) + 2, end(input))); +#endif // __EDG__ +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // special member functions +#ifndef __EDG__ // TRANSITION, VSO-1274387 vec default_constructed; vec copy_constructed(size_default_constructed); +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273296 assert(equal(copy_constructed.begin(), copy_constructed.end(), size_default_constructed.begin(), size_default_constructed.end())); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL ! =2 vec move_constructed(move(copy_constructed)); +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273296 assert(equal(move_constructed.begin(), move_constructed.end(), size_default_constructed.begin(), size_default_constructed.end())); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL ! =2 assert(copy_constructed.empty()); +#endif // __EDG__ +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273365 +#ifndef __EDG__ // TRANSITION, VSO-1274387, VSO-1273296 vec copy_assigned = range_constructed; assert(equal(copy_assigned.begin(), copy_assigned.end(), range_constructed.begin(), range_constructed.end())); vec move_assigned = std::move(copy_assigned); assert(equal(move_assigned.begin(), move_assigned.end(), range_constructed.begin(), range_constructed.end())); assert(copy_assigned.empty()); +#endif // __EDG__ +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // allocator constructors soccc_allocator alloc(2, 3); assert(alloc.id == 2); assert(alloc.soccc_generation == 3); +#ifndef __EDG__ // TRANSITION, VSO-1274387 vec al_default_constructed(alloc); assert(al_default_constructed.empty()); assert(al_default_constructed.get_allocator().id == 4); assert(al_default_constructed.get_allocator().soccc_generation == 3); vec al_copy_constructed(size_value_constructed, alloc); +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273296 assert(all_of(al_copy_constructed.begin(), al_copy_constructed.end(), [](const bool val) { return val; })); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 assert(al_copy_constructed.get_allocator().id == 4); assert(al_copy_constructed.get_allocator().soccc_generation == 3); vec al_move_constructed(move(al_copy_constructed), alloc); +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273296 assert(all_of(al_move_constructed.begin(), al_move_constructed.end(), [](const bool val) { return val; })); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 assert(al_copy_constructed.empty()); assert(al_move_constructed.get_allocator().id == 4); assert(al_move_constructed.get_allocator().soccc_generation == 3); vec al_size_default_constructed(5, alloc); assert(al_size_default_constructed.size() == 5); +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273296 assert(all_of(al_size_default_constructed.begin(), al_size_default_constructed.end(), [](const bool val) { return !val; })); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 assert(al_size_default_constructed.get_allocator().id == 4); assert(al_size_default_constructed.get_allocator().soccc_generation == 3); vec al_size_value_constructed(5, true, alloc); assert(al_size_value_constructed.size() == 5); +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273296 assert(all_of( al_size_value_constructed.begin(), al_size_value_constructed.end(), [](const bool val) { return val; })); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 assert(al_size_value_constructed.get_allocator().id == 4); assert(al_size_value_constructed.get_allocator().soccc_generation == 3); +#endif // __EDG__ +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273365 +#ifndef __EDG__ // TRANSITION, VSO-1274387 vec al_range_constructed(begin(input), end(input), alloc); assert(equal(al_range_constructed.begin(), al_range_constructed.end(), begin(input), end(input))); assert(al_range_constructed.get_allocator().id == 4); assert(al_range_constructed.get_allocator().soccc_generation == 3); +#endif // __EDG__ +#ifndef __EDG__ // TRANSITION, VSO-1274387 vec al_initializer_list_constructed({true, true, false, true}, alloc); assert(equal(al_initializer_list_constructed.begin(), al_initializer_list_constructed.end(), begin(input) + 2, end(input))); assert(al_initializer_list_constructed.get_allocator().id == 4); assert(al_initializer_list_constructed.get_allocator().soccc_generation == 3); +#endif // __EDG__ +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 } { // assignment +#ifndef __EDG__ // TRANSITION, VSO-1274387 vec range_constructed(begin(input), end(input)); vec copy_constructed; @@ -179,20 +221,25 @@ _CONSTEXPR20_CONTAINER bool test_interface() { assigned.assign({true, false, true, true, false, true}); assert(equal( assigned.begin(), assigned.end(), begin(expected_assign_initializer), end(expected_assign_initializer))); +#endif // __EDG__ } { // allocator +#ifndef __EDG__ // TRANSITION, VSO-1274387 vec default_constructed; const auto alloc = default_constructed.get_allocator(); static_assert(is_same_v, soccc_allocator>); assert(alloc.id == 1); assert(alloc.soccc_generation == 0); +#endif // __EDG__ } { // iterators +#ifndef __EDG__ // TRANSITION, VSO-1274387 vec range_constructed(begin(input), end(input)); const vec const_range_constructed(begin(input), end(input)); +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273381 const auto b = range_constructed.begin(); static_assert(is_same_v, vec::iterator>); assert(*b); @@ -240,12 +287,16 @@ _CONSTEXPR20_CONTAINER bool test_interface() { const auto cre2 = const_range_constructed.rend(); static_assert(is_same_v, reverse_iterator>); assert(*prev(cre2)); +#endif // defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 +#endif // __EDG__ } { // access +#ifndef __EDG__ // TRANSITION, VSO-1274387 vec range_constructed(begin(input), end(input)); const vec const_range_constructed(begin(input), end(input)); +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273381 const auto at = range_constructed.at(2); static_assert(is_same_v, _Iter_ref_t>); assert(at); @@ -288,9 +339,12 @@ _CONSTEXPR20_CONTAINER bool test_interface() { const auto cb = const_range_constructed.back(); static_assert(is_same_v, _Iter_ref_t>); assert(cb); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 +#endif // __EDG__ } { // capacity +#ifndef __EDG__ // TRANSITION, VSO-1274387 vec range_constructed(begin(input), end(input)); const auto e = range_constructed.empty(); @@ -316,9 +370,11 @@ _CONSTEXPR20_CONTAINER bool test_interface() { const auto c2 = range_constructed.capacity(); static_assert(is_same_v, std::size_t>); assert(c2 == 32); +#endif // __EDG__ } { // modifiers +#ifndef __EDG__ // TRANSITION, VSO-1274387 vec range_constructed(begin(input), end(input)); vec cleared = range_constructed; @@ -346,6 +402,7 @@ _CONSTEXPR20_CONTAINER bool test_interface() { assert(inserted.size() == 4); assert(inserted.front() == false); +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273381 const auto it = inserted.insert(inserted.begin(), begin(input), end(input)); assert(inserted.size() == 10); assert(it == inserted.begin()); @@ -357,6 +414,7 @@ _CONSTEXPR20_CONTAINER bool test_interface() { const auto it3 = inserted.insert(inserted.begin(), {true, false, true}); assert(inserted.size() == 19); assert(it3 == inserted.begin()); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 inserted.insert(inserted.cbegin(), {false, true, false}); assert(inserted.size() == 22); @@ -391,9 +449,11 @@ _CONSTEXPR20_CONTAINER bool test_interface() { assert(inserted.size() == 1); assert(inserted.front() == false); assert(emplaced.size() == 22); +#endif // __EDG__ } { // swap +#ifndef __EDG__ // TRANSITION, VSO-1274387 vec first{true, false, true}; vec second{false, false, true, false}; swap(first, second); @@ -402,9 +462,11 @@ _CONSTEXPR20_CONTAINER bool test_interface() { constexpr bool expected_second[] = {true, false, true}; assert(equal(first.begin(), first.end(), begin(expected_first), end(expected_first))); assert(equal(second.begin(), second.end(), begin(expected_second), end(expected_second))); +#endif // __EDG__ } { // erase +#ifndef __EDG__ // TRANSITION, UPDATE ME: xmemory:1858 access to uninitialized object vec erased{false, false, true, false, true}; erase(erased, false); constexpr bool expected_erased[] = {true, true}; @@ -414,9 +476,11 @@ _CONSTEXPR20_CONTAINER bool test_interface() { erase_if(erased_if, [](const bool val) { return val; }); constexpr bool expected_erase_if[] = {false, false, false}; assert(equal(erased_if.begin(), erased_if.end(), begin(expected_erase_if), end(expected_erase_if))); +#endif // __EDG__ } { // comparison +#ifndef __EDG__ // TRANSITION, UPDATE ME: xmemory:1858 access to uninitialized object vec first(begin(input), end(input)); vec second(begin(input), end(input)); vec third{true, false, true}; @@ -428,13 +492,19 @@ _CONSTEXPR20_CONTAINER bool test_interface() { const auto ne = first != third; static_assert(is_same_v, bool>); assert(ne); +#endif // __EDG__ } +#endif // defined(MSVC_INTERNAL_TESTING) || defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 + return true; } _CONSTEXPR20_CONTAINER bool test_iterators() { +#if defined(MSVC_INTERNAL_TESTING) || defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1270433 +#ifndef __EDG__ // TRANSITION, UPDATE ME: xmemory:1858 access to uninitialized object vec range_constructed(begin(input), end(input)); +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273381 { // increment auto it = range_constructed.begin(); assert(*++it == false); @@ -524,6 +594,9 @@ _CONSTEXPR20_CONTAINER bool test_iterators() { const auto cit2 = vec2.cbegin(); assert(cit2->first == false); } +#endif // __EDG__ +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 +#endif // defined(MSVC_INTERNAL_TESTING) || defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 return true; } From 634acd5e6c54ca0e2e7f325bc973f50a8f0d6efe Mon Sep 17 00:00:00 2001 From: Miya Natsuhara Date: Thu, 4 Feb 2021 17:15:18 -0800 Subject: [PATCH 18/50] add workaround for DevCom-1331017 --- stl/inc/vector | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/stl/inc/vector b/stl/inc/vector index fd29ca88265..ec731cebf04 100644 --- a/stl/inc/vector +++ b/stl/inc/vector @@ -1996,6 +1996,9 @@ public: this->_Adopt(_Mypvbool); } + // TRANSITION, DevCom-1331017 + _CONSTEXPR20_CONTAINER _Vb_iter_base& operator=(const _Vb_iter_base&) noexcept = default; + _CONSTEXPR20_CONTAINER void _Advance(_Size_type _Off) noexcept { _Myoff += _Off; _Myptr += _Myoff / _VBITS; @@ -2103,6 +2106,9 @@ public: _CONSTEXPR20_CONTAINER _Vb_const_iterator(const _Vbase* _Ptr, const _Container_base* _Mypvbool) noexcept : _Mybase(_Ptr, 0, _Mypvbool) {} + // TRANSITION, DevCom-1331017 + _CONSTEXPR20_CONTAINER _Vb_const_iterator& operator=(const _Vb_const_iterator&) noexcept = default; + _NODISCARD _CONSTEXPR20_CONTAINER const_reference operator*() const noexcept { #if _ITERATOR_DEBUG_LEVEL != 0 #ifdef __cpp_lib_constexpr_dynamic_alloc @@ -2331,6 +2337,9 @@ public: return _Reft(*this); } + // TRANSITION, DevCom-1331017 + _CONSTEXPR20_CONTAINER _Vb_iterator& operator=(const _Vb_iterator&) noexcept = default; + _CONSTEXPR20_CONTAINER _Vb_iterator& operator++() noexcept { _Mybase::operator++(); return *this; From 3edeeaa63b9acadc2288fbdc167632307d26adc2 Mon Sep 17 00:00:00 2001 From: Miya Natsuhara Date: Thu, 4 Feb 2021 17:21:42 -0800 Subject: [PATCH 19/50] Missed updating a few comments with bug numbers in vector bool tests --- tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp b/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp index de660537442..964cc522ab6 100644 --- a/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp +++ b/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp @@ -466,7 +466,7 @@ _CONSTEXPR20_CONTAINER bool test_interface() { } { // erase -#ifndef __EDG__ // TRANSITION, UPDATE ME: xmemory:1858 access to uninitialized object +#ifndef __EDG__ // TRANSITION, VSO-1274387 vec erased{false, false, true, false, true}; erase(erased, false); constexpr bool expected_erased[] = {true, true}; @@ -480,7 +480,7 @@ _CONSTEXPR20_CONTAINER bool test_interface() { } { // comparison -#ifndef __EDG__ // TRANSITION, UPDATE ME: xmemory:1858 access to uninitialized object +#ifndef __EDG__ // TRANSITION, VSO-1274387 vec first(begin(input), end(input)); vec second(begin(input), end(input)); vec third{true, false, true}; @@ -501,7 +501,7 @@ _CONSTEXPR20_CONTAINER bool test_interface() { _CONSTEXPR20_CONTAINER bool test_iterators() { #if defined(MSVC_INTERNAL_TESTING) || defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1270433 -#ifndef __EDG__ // TRANSITION, UPDATE ME: xmemory:1858 access to uninitialized object +#ifndef __EDG__ // TRANSITION, VSO-1274387 vec range_constructed(begin(input), end(input)); #if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273381 From 5a32d990ccb7ce6f36025f5b74500720757e276c Mon Sep 17 00:00:00 2001 From: Miya Natsuhara Date: Fri, 5 Feb 2021 10:52:01 -0800 Subject: [PATCH 20/50] address some review comments --- stl/inc/vector | 344 +++++++++++++------------------------------ stl/inc/xmemory | 2 - stl/inc/yvals_core.h | 4 +- 3 files changed, 101 insertions(+), 249 deletions(-) diff --git a/stl/inc/vector b/stl/inc/vector index ec731cebf04..46cb0186841 100644 --- a/stl/inc/vector +++ b/stl/inc/vector @@ -45,15 +45,10 @@ public: _NODISCARD _CONSTEXPR20_CONTAINER reference operator*() const noexcept { #if _ITERATOR_DEBUG_LEVEL != 0 -#ifdef __cpp_lib_constexpr_dynamic_alloc - if (!_STD is_constant_evaluated()) -#endif // __cpp_lib_constexpr_dynamic_alloc - { - const auto _Mycont = static_cast(this->_Getcont()); - _STL_VERIFY(_Ptr, "can't dereference value-initialized vector iterator"); - _STL_VERIFY( - _Mycont->_Myfirst <= _Ptr && _Ptr < _Mycont->_Mylast, "can't dereference out of range vector iterator"); - } + const auto _Mycont = static_cast(this->_Getcont()); + _STL_VERIFY(_Ptr, "can't dereference value-initialized vector iterator"); + _STL_VERIFY( + _Mycont->_Myfirst <= _Ptr && _Ptr < _Mycont->_Mylast, "can't dereference out of range vector iterator"); #endif // _ITERATOR_DEBUG_LEVEL != 0 return *_Ptr; @@ -61,15 +56,10 @@ public: _NODISCARD _CONSTEXPR20_CONTAINER pointer operator->() const noexcept { #if _ITERATOR_DEBUG_LEVEL != 0 -#ifdef __cpp_lib_constexpr_dynamic_alloc - if (!_STD is_constant_evaluated()) -#endif // __cpp_lib_constexpr_dynamic_alloc - { - const auto _Mycont = static_cast(this->_Getcont()); - _STL_VERIFY(_Ptr, "can't dereference value-initialized vector iterator"); - _STL_VERIFY( - _Mycont->_Myfirst <= _Ptr && _Ptr < _Mycont->_Mylast, "can't dereference out of range vector iterator"); - } + const auto _Mycont = static_cast(this->_Getcont()); + _STL_VERIFY(_Ptr, "can't dereference value-initialized vector iterator"); + _STL_VERIFY( + _Mycont->_Myfirst <= _Ptr && _Ptr < _Mycont->_Mylast, "can't dereference out of range vector iterator"); #endif // _ITERATOR_DEBUG_LEVEL != 0 return _Ptr; @@ -77,14 +67,9 @@ public: _CONSTEXPR20_CONTAINER _Vector_const_iterator& operator++() noexcept { #if _ITERATOR_DEBUG_LEVEL != 0 -#ifdef __cpp_lib_constexpr_dynamic_alloc - if (!_STD is_constant_evaluated()) -#endif // __cpp_lib_constexpr_dynamic_alloc - { - const auto _Mycont = static_cast(this->_Getcont()); - _STL_VERIFY(_Ptr, "can't increment value-initialized vector iterator"); - _STL_VERIFY(_Ptr < _Mycont->_Mylast, "can't increment vector iterator past end"); - } + const auto _Mycont = static_cast(this->_Getcont()); + _STL_VERIFY(_Ptr, "can't increment value-initialized vector iterator"); + _STL_VERIFY(_Ptr < _Mycont->_Mylast, "can't increment vector iterator past end"); #endif // _ITERATOR_DEBUG_LEVEL != 0 ++_Ptr; @@ -99,14 +84,9 @@ public: _CONSTEXPR20_CONTAINER _Vector_const_iterator& operator--() noexcept { #if _ITERATOR_DEBUG_LEVEL != 0 -#ifdef __cpp_lib_constexpr_dynamic_alloc - if (!_STD is_constant_evaluated()) -#endif // __cpp_lib_constexpr_dynamic_alloc - { - const auto _Mycont = static_cast(this->_Getcont()); - _STL_VERIFY(_Ptr, "can't decrement value-initialized vector iterator"); - _STL_VERIFY(_Mycont->_Myfirst < _Ptr, "can't decrement vector iterator before begin"); - } + const auto _Mycont = static_cast(this->_Getcont()); + _STL_VERIFY(_Ptr, "can't decrement value-initialized vector iterator"); + _STL_VERIFY(_Mycont->_Myfirst < _Ptr, "can't decrement vector iterator before begin"); #endif // _ITERATOR_DEBUG_LEVEL != 0 --_Ptr; @@ -123,19 +103,14 @@ public: #if _ITERATOR_DEBUG_LEVEL == 0 (void) _Off; #else // ^^^ _ITERATOR_DEBUG_LEVEL == 0 ^^^ // vvv _ITERATOR_DEBUG_LEVEL != 0 vvv -#ifdef __cpp_lib_constexpr_dynamic_alloc - if (!_STD is_constant_evaluated()) -#endif // __cpp_lib_constexpr_dynamic_alloc - { - const auto _Mycont = static_cast(this->_Getcont()); - _STL_VERIFY(_Off == 0 || _Ptr, "cannot seek value-initialized vector iterator"); - if (_Off < 0) { - _STL_VERIFY(_Off >= _Mycont->_Myfirst - _Ptr, "cannot seek vector iterator before begin"); - } + const auto _Mycont = static_cast(this->_Getcont()); + _STL_VERIFY(_Off == 0 || _Ptr, "cannot seek value-initialized vector iterator"); + if (_Off < 0) { + _STL_VERIFY(_Off >= _Mycont->_Myfirst - _Ptr, "cannot seek vector iterator before begin"); + } - if (_Off > 0) { - _STL_VERIFY(_Off <= _Mycont->_Mylast - _Ptr, "cannot seek vector iterator after end"); - } + if (_Off > 0) { + _STL_VERIFY(_Off <= _Mycont->_Mylast - _Ptr, "cannot seek vector iterator after end"); } #endif // _ITERATOR_DEBUG_LEVEL == 0 } @@ -200,26 +175,15 @@ public: #if _ITERATOR_DEBUG_LEVEL == 0 (void) _Right; #else // ^^^ _ITERATOR_DEBUG_LEVEL == 0 ^^^ // vvv _ITERATOR_DEBUG_LEVEL != 0 vvv -#ifdef __cpp_lib_constexpr_dynamic_alloc - if (!_STD is_constant_evaluated()) -#endif // __cpp_lib_constexpr_dynamic_alloc - { - _STL_VERIFY(this->_Getcont() == _Right._Getcont(), "vector iterators incompatible"); - } + _STL_VERIFY(this->_Getcont() == _Right._Getcont(), "vector iterators incompatible"); #endif // _ITERATOR_DEBUG_LEVEL == 0 } #if _ITERATOR_DEBUG_LEVEL != 0 friend _CONSTEXPR20_CONTAINER void _Verify_range( const _Vector_const_iterator& _First, const _Vector_const_iterator& _Last) noexcept { -#ifdef __cpp_lib_constexpr_dynamic_alloc - if (!_STD is_constant_evaluated()) -#endif // __cpp_lib_constexpr_dynamic_alloc - { - _STL_VERIFY( - _First._Getcont() == _Last._Getcont(), "vector iterators in range are from different containers"); - _STL_VERIFY(_First._Ptr <= _Last._Ptr, "vector iterator range transposed"); - } + _STL_VERIFY(_First._Getcont() == _Last._Getcont(), "vector iterators in range are from different containers"); + _STL_VERIFY(_First._Ptr <= _Last._Ptr, "vector iterator range transposed"); } #endif // _ITERATOR_DEBUG_LEVEL != 0 @@ -255,17 +219,12 @@ struct pointer_traits<_Vector_const_iterator<_Myvec>> { // capacity() of 0 is not. This function cannot distinguish those two cases, so it incorrectly does not diagnose // the latter. In practice, this isn't a significant problem since to_address returns nullptr for such an // iterator. -#ifdef __cpp_lib_constexpr_dynamic_alloc - if (!_STD is_constant_evaluated()) -#endif // __cpp_lib_constexpr_dynamic_alloc - { - const auto _Mycont = static_cast(_Iter._Getcont()); - if (_Mycont) { - _STL_VERIFY(_Mycont->_Myfirst <= _Iter._Ptr && _Iter._Ptr <= _Mycont->_Mylast, - "can't convert out-of-range vector iterator to pointer"); - } else { - _STL_VERIFY(!_Iter._Ptr, "can't convert invalid vector iterator to pointer"); - } + const auto _Mycont = static_cast(_Iter._Getcont()); + if (_Mycont) { + _STL_VERIFY(_Mycont->_Myfirst <= _Iter._Ptr && _Iter._Ptr <= _Mycont->_Mylast, + "can't convert out-of-range vector iterator to pointer"); + } else { + _STL_VERIFY(!_Iter._Ptr, "can't convert invalid vector iterator to pointer"); } #endif // _ITERATOR_DEBUG_LEVEL != 0 @@ -297,15 +256,10 @@ public: _NODISCARD _CONSTEXPR20_CONTAINER pointer operator->() const noexcept { #if _ITERATOR_DEBUG_LEVEL != 0 -#ifdef __cpp_lib_constexpr_dynamic_alloc - if (!_STD is_constant_evaluated()) -#endif // __cpp_lib_constexpr_dynamic_alloc - { - const auto _Mycont = static_cast(this->_Getcont()); - _STL_VERIFY(this->_Ptr, "can't dereference value-initialized vector iterator"); - _STL_VERIFY(_Mycont->_Myfirst <= this->_Ptr && this->_Ptr < _Mycont->_Mylast, - "can't dereference out of range vector iterator"); - } + const auto _Mycont = static_cast(this->_Getcont()); + _STL_VERIFY(this->_Ptr, "can't dereference value-initialized vector iterator"); + _STL_VERIFY(_Mycont->_Myfirst <= this->_Ptr && this->_Ptr < _Mycont->_Mylast, + "can't dereference out of range vector iterator"); #endif // _ITERATOR_DEBUG_LEVEL != 0 return this->_Ptr; @@ -385,17 +339,12 @@ struct pointer_traits<_Vector_iterator<_Myvec>> { // capacity() of 0 is not. This function cannot distinguish those two cases, so it incorrectly does not diagnose // the latter. In practice, this isn't a significant problem since to_address returns nullptr for such an // iterator. -#ifdef __cpp_lib_constexpr_dynamic_alloc - if (!_STD is_constant_evaluated()) -#endif // __cpp_lib_constexpr_dynamic_alloc - { - const auto _Mycont = static_cast(_Iter._Getcont()); - if (_Mycont) { - _STL_VERIFY(_Mycont->_Myfirst <= _Iter._Ptr && _Iter._Ptr <= _Mycont->_Mylast, - "can't convert out-of-range vector iterator to pointer"); - } else { - _STL_VERIFY(!_Iter._Ptr, "can't convert invalid vector iterator to pointer"); - } + const auto _Mycont = static_cast(_Iter._Getcont()); + if (_Mycont) { + _STL_VERIFY(_Mycont->_Myfirst <= _Iter._Ptr && _Iter._Ptr <= _Mycont->_Mylast, + "can't convert out-of-range vector iterator to pointer"); + } else { + _STL_VERIFY(!_Iter._Ptr, "can't convert invalid vector iterator to pointer"); } #endif // _ITERATOR_DEBUG_LEVEL != 0 @@ -462,13 +411,13 @@ public: // FUNCTION TEMPLATE _Unfancy_maybe_null template -_CONSTEXPR20_CONTAINER auto _Unfancy_maybe_null(_Ptrty _Ptr) noexcept { +constexpr auto _Unfancy_maybe_null(_Ptrty _Ptr) noexcept { // converts from a (potentially null) fancy pointer to a plain pointer return _Ptr ? _STD addressof(*_Ptr) : nullptr; } template -_CONSTEXPR20_CONTAINER _Ty* _Unfancy_maybe_null(_Ty* _Ptr) noexcept { // do nothing for plain pointers +constexpr _Ty* _Unfancy_maybe_null(_Ty* _Ptr) noexcept { // do nothing for plain pointers return _Ptr; } @@ -847,14 +796,9 @@ public: auto& _My_data = _Mypair._Myval2; const pointer _Oldlast = _My_data._Mylast; #if _ITERATOR_DEBUG_LEVEL == 2 -#ifdef __cpp_lib_constexpr_dynamic_alloc - if (!_STD is_constant_evaluated()) -#endif // __cpp_lib_constexpr_dynamic_alloc - { - _STL_VERIFY(_Where._Getcont() == _STD addressof(_My_data) && _Whereptr >= _My_data._Myfirst - && _Oldlast >= _Whereptr, - "vector emplace iterator outside range"); - } + _STL_VERIFY( + _Where._Getcont() == _STD addressof(_My_data) && _Whereptr >= _My_data._Myfirst && _Oldlast >= _Whereptr, + "vector emplace iterator outside range"); #endif // _ITERATOR_DEBUG_LEVEL == 2 if (_Oldlast != _My_data._Myend) { @@ -896,14 +840,8 @@ public: const pointer _Oldfirst = _My_data._Myfirst; const pointer _Oldlast = _Mylast; #if _ITERATOR_DEBUG_LEVEL == 2 -#ifdef __cpp_lib_constexpr_dynamic_alloc - if (!_STD is_constant_evaluated()) -#endif // __cpp_lib_constexpr_dynamic_alloc - { - _STL_VERIFY( - _Where._Getcont() == _STD addressof(_My_data) && _Whereptr >= _Oldfirst && _Oldlast >= _Whereptr, - "vector insert iterator outside range"); - } + _STL_VERIFY(_Where._Getcont() == _STD addressof(_My_data) && _Whereptr >= _Oldfirst && _Oldlast >= _Whereptr, + "vector insert iterator outside range"); #endif // _ITERATOR_DEBUG_LEVEL == 2 const auto _Whereoff = static_cast(_Whereptr - _Oldfirst); @@ -1106,14 +1044,9 @@ public: auto& _My_data = _Mypair._Myval2; const pointer _Oldfirst = _My_data._Myfirst; #if _ITERATOR_DEBUG_LEVEL == 2 -#ifdef __cpp_lib_constexpr_dynamic_alloc - if (!_STD is_constant_evaluated()) -#endif // __cpp_lib_constexpr_dynamic_alloc - { - _STL_VERIFY(_Where._Getcont() == _STD addressof(_My_data) && _Whereptr >= _Oldfirst - && _My_data._Mylast >= _Whereptr, - "vector insert iterator outside range"); - } + _STL_VERIFY( + _Where._Getcont() == _STD addressof(_My_data) && _Whereptr >= _Oldfirst && _My_data._Mylast >= _Whereptr, + "vector insert iterator outside range"); #endif // _ITERATOR_DEBUG_LEVEL == 2 _Adl_verify_range(_First, _Last); @@ -1445,12 +1378,7 @@ public: pointer& _Mylast = _My_data._Mylast; #if _ITERATOR_DEBUG_LEVEL == 2 -#ifdef __cpp_lib_constexpr_dynamic_alloc - if (!_STD is_constant_evaluated()) -#endif // __cpp_lib_constexpr_dynamic_alloc - { - _STL_VERIFY(_My_data._Myfirst != _Mylast, "vector empty before pop"); - } + _STL_VERIFY(_My_data._Myfirst != _Mylast, "vector empty before pop"); #endif // _ITERATOR_DEBUG_LEVEL == 2 _Orphan_range(_Mylast - 1, _Mylast); @@ -1465,14 +1393,9 @@ public: pointer& _Mylast = _My_data._Mylast; #if _ITERATOR_DEBUG_LEVEL == 2 -#ifdef __cpp_lib_constexpr_dynamic_alloc - if (!_STD is_constant_evaluated()) -#endif // __cpp_lib_constexpr_dynamic_alloc - { - _STL_VERIFY( - _Where._Getcont() == _STD addressof(_My_data) && _Whereptr >= _My_data._Myfirst && _Mylast > _Whereptr, - "vector erase iterator outside range"); - } + _STL_VERIFY( + _Where._Getcont() == _STD addressof(_My_data) && _Whereptr >= _My_data._Myfirst && _Mylast > _Whereptr, + "vector erase iterator outside range"); #endif // _ITERATOR_DEBUG_LEVEL == 2 _Orphan_range(_Whereptr, _Mylast); @@ -1490,14 +1413,9 @@ public: pointer& _Mylast = _My_data._Mylast; #if _ITERATOR_DEBUG_LEVEL == 2 -#ifdef __cpp_lib_constexpr_dynamic_alloc - if (!_STD is_constant_evaluated()) -#endif // __cpp_lib_constexpr_dynamic_alloc - { - _STL_VERIFY(_First._Getcont() == _STD addressof(_My_data) && _Last._Getcont() == _STD addressof(_My_data) - && _Firstptr >= _My_data._Myfirst && _Lastptr >= _Firstptr && _Mylast >= _Lastptr, - "vector erase iterator outside range"); - } + _STL_VERIFY(_First._Getcont() == _STD addressof(_My_data) && _Last._Getcont() == _STD addressof(_My_data) + && _Firstptr >= _My_data._Myfirst && _Lastptr >= _Firstptr && _Mylast >= _Lastptr, + "vector erase iterator outside range"); #endif // _ITERATOR_DEBUG_LEVEL == 2 if (_Firstptr != _Lastptr) { // something to do, invalidate iterators @@ -1521,7 +1439,6 @@ public: _Mylast = _Myfirst; } -public: _CONSTEXPR20_CONTAINER void swap(vector& _Right) noexcept /* strengthened */ { if (this != _STD addressof(_Right)) { _Pocs(_Getal(), _Right._Getal()); @@ -1628,13 +1545,8 @@ public: _NODISCARD _CONSTEXPR20_CONTAINER _Ty& operator[](const size_type _Pos) noexcept /* strengthened */ { auto& _My_data = _Mypair._Myval2; #if _CONTAINER_DEBUG_LEVEL > 0 -#ifdef __cpp_lib_constexpr_dynamic_alloc - if (!_STD is_constant_evaluated()) -#endif // __cpp_lib_constexpr_dynamic_alloc - { - _STL_VERIFY( - _Pos < static_cast(_My_data._Mylast - _My_data._Myfirst), "vector subscript out of range"); - } + _STL_VERIFY( + _Pos < static_cast(_My_data._Mylast - _My_data._Myfirst), "vector subscript out of range"); #endif // _CONTAINER_DEBUG_LEVEL > 0 return _My_data._Myfirst[_Pos]; @@ -1643,13 +1555,8 @@ public: _NODISCARD _CONSTEXPR20_CONTAINER const _Ty& operator[](const size_type _Pos) const noexcept /* strengthened */ { auto& _My_data = _Mypair._Myval2; #if _CONTAINER_DEBUG_LEVEL > 0 -#ifdef __cpp_lib_constexpr_dynamic_alloc - if (!_STD is_constant_evaluated()) -#endif // __cpp_lib_constexpr_dynamic_alloc - { - _STL_VERIFY( - _Pos < static_cast(_My_data._Mylast - _My_data._Myfirst), "vector subscript out of range"); - } + _STL_VERIFY( + _Pos < static_cast(_My_data._Mylast - _My_data._Myfirst), "vector subscript out of range"); #endif // _CONTAINER_DEBUG_LEVEL > 0 return _My_data._Myfirst[_Pos]; @@ -1676,12 +1583,7 @@ public: _NODISCARD _CONSTEXPR20_CONTAINER _Ty& front() noexcept /* strengthened */ { auto& _My_data = _Mypair._Myval2; #if _CONTAINER_DEBUG_LEVEL > 0 -#ifdef __cpp_lib_constexpr_dynamic_alloc - if (!_STD is_constant_evaluated()) -#endif // __cpp_lib_constexpr_dynamic_alloc - { - _STL_VERIFY(_My_data._Myfirst != _My_data._Mylast, "front() called on empty vector"); - } + _STL_VERIFY(_My_data._Myfirst != _My_data._Mylast, "front() called on empty vector"); #endif // _CONTAINER_DEBUG_LEVEL > 0 return *_My_data._Myfirst; @@ -1690,12 +1592,7 @@ public: _NODISCARD _CONSTEXPR20_CONTAINER const _Ty& front() const noexcept /* strengthened */ { auto& _My_data = _Mypair._Myval2; #if _CONTAINER_DEBUG_LEVEL > 0 -#ifdef __cpp_lib_constexpr_dynamic_alloc - if (!_STD is_constant_evaluated()) -#endif // __cpp_lib_constexpr_dynamic_alloc - { - _STL_VERIFY(_My_data._Myfirst != _My_data._Mylast, "front() called on empty vector"); - } + _STL_VERIFY(_My_data._Myfirst != _My_data._Mylast, "front() called on empty vector"); #endif // _CONTAINER_DEBUG_LEVEL > 0 return *_My_data._Myfirst; @@ -1704,12 +1601,7 @@ public: _NODISCARD _CONSTEXPR20_CONTAINER _Ty& back() noexcept /* strengthened */ { auto& _My_data = _Mypair._Myval2; #if _CONTAINER_DEBUG_LEVEL > 0 -#ifdef __cpp_lib_constexpr_dynamic_alloc - if (!_STD is_constant_evaluated()) -#endif // __cpp_lib_constexpr_dynamic_alloc - { - _STL_VERIFY(_My_data._Myfirst != _My_data._Mylast, "back() called on empty vector"); - } + _STL_VERIFY(_My_data._Myfirst != _My_data._Mylast, "back() called on empty vector"); #endif // _CONTAINER_DEBUG_LEVEL > 0 return _My_data._Mylast[-1]; @@ -1718,12 +1610,7 @@ public: _NODISCARD _CONSTEXPR20_CONTAINER const _Ty& back() const noexcept /* strengthened */ { auto& _My_data = _Mypair._Myval2; #if _CONTAINER_DEBUG_LEVEL > 0 -#ifdef __cpp_lib_constexpr_dynamic_alloc - if (!_STD is_constant_evaluated()) -#endif // __cpp_lib_constexpr_dynamic_alloc - { - _STL_VERIFY(_My_data._Myfirst != _My_data._Mylast, "back() called on empty vector"); - } + _STL_VERIFY(_My_data._Myfirst != _My_data._Mylast, "back() called on empty vector"); #endif // _CONTAINER_DEBUG_LEVEL > 0 return _My_data._Mylast[-1]; @@ -1771,7 +1658,8 @@ private: bool_constant, negation>>>{}); } - _CONSTEXPR20_CONTAINER void _Destroy(pointer _First, pointer _Last) { // destroy [_First, _Last) using allocator + _CONSTEXPR20_CONTAINER void _Destroy(pointer _First, pointer _Last) { + // destroy [_First, _Last) using allocator _Destroy_range(_First, _Last, _Getal()); } @@ -1893,6 +1781,7 @@ private: } _CONSTEXPR20_CONTAINER void _Orphan_range(pointer _First, pointer _Last) const { + // orphan iterators within specified (inclusive) range #ifdef __cpp_lib_constexpr_dynamic_alloc if (_STD is_constant_evaluated()) { _Orphan_range_unlocked(_First, _Last); @@ -2056,15 +1945,10 @@ public: _CONSTEXPR20_CONTAINER const _Vbase* _Getptr() const noexcept { #if _ITERATOR_DEBUG_LEVEL != 0 -#ifdef __cpp_lib_constexpr_dynamic_alloc - if (!_STD is_constant_evaluated()) -#endif // __cpp_lib_constexpr_dynamic_alloc - { - const auto _Cont = static_cast(this->_Getcont()); - _STL_VERIFY(_Cont, "cannot dereference value-initialized vector iterator"); - _STL_VERIFY(this->_Total_off(_Cont) <= static_cast<_Difference_type>(_Cont->_Mysize), - "vector iterator not dereferenceable"); - } + const auto _Cont = static_cast(this->_Getcont()); + _STL_VERIFY(_Cont, "cannot dereference value-initialized vector iterator"); + _STL_VERIFY(this->_Total_off(_Cont) <= static_cast<_Difference_type>(_Cont->_Mysize), + "vector iterator not dereferenceable"); #endif // _ITERATOR_DEBUG_LEVEL != 0 return this->_Myptr; @@ -2111,15 +1995,10 @@ public: _NODISCARD _CONSTEXPR20_CONTAINER const_reference operator*() const noexcept { #if _ITERATOR_DEBUG_LEVEL != 0 -#ifdef __cpp_lib_constexpr_dynamic_alloc - if (!_STD is_constant_evaluated()) -#endif // __cpp_lib_constexpr_dynamic_alloc - { - const auto _Cont = static_cast(this->_Getcont()); - _STL_VERIFY(_Cont, "cannot dereference value-initialized vector iterator"); - _STL_VERIFY(this->_Total_off(_Cont) < static_cast<_Difference_type>(_Cont->_Mysize), - "vector iterator not dereferenceable"); - } + const auto _Cont = static_cast(this->_Getcont()); + _STL_VERIFY(_Cont, "cannot dereference value-initialized vector iterator"); + _STL_VERIFY(this->_Total_off(_Cont) < static_cast<_Difference_type>(_Cont->_Mysize), + "vector iterator not dereferenceable"); #endif // _ITERATOR_DEBUG_LEVEL != 0 return _Reft(*this); @@ -2149,20 +2028,15 @@ public: _CONSTEXPR20_CONTAINER _Vb_const_iterator& operator+=(const difference_type _Off) noexcept { #if _ITERATOR_DEBUG_LEVEL != 0 -#ifdef __cpp_lib_constexpr_dynamic_alloc - if (!_STD is_constant_evaluated()) -#endif // __cpp_lib_constexpr_dynamic_alloc - { - if (_Off != 0) { - const auto _Cont = static_cast(this->_Getcont()); - _STL_VERIFY(_Cont, "cannot seek value-initialized vector iterator"); - const auto _Start_offset = this->_Total_off(_Cont); - if (_Off < 0) { - _STL_VERIFY(-_Start_offset <= _Off, "cannot seek vector iterator before begin"); - } else if (0 < _Off) { - _STL_VERIFY(_Off <= static_cast<_Difference_type>(_Cont->_Mysize - _Start_offset), - "cannot seek vector iterator after end"); - } + if (_Off != 0) { + const auto _Cont = static_cast(this->_Getcont()); + _STL_VERIFY(_Cont, "cannot seek value-initialized vector iterator"); + const auto _Start_offset = this->_Total_off(_Cont); + if (_Off < 0) { + _STL_VERIFY(-_Start_offset <= _Off, "cannot seek vector iterator before begin"); + } else if (0 < _Off) { + _STL_VERIFY(_Off <= static_cast<_Difference_type>(_Cont->_Mysize - _Start_offset), + "cannot seek vector iterator after end"); } } #endif // _ITERATOR_DEBUG_LEVEL != 0 @@ -2229,17 +2103,12 @@ public: return !(*this < _Right); } - _CONSTEXPR20_CONTAINER void _Compat( - const _Vb_const_iterator& _Right) const noexcept { // test for compatible iterator pair + _CONSTEXPR20_CONTAINER void _Compat(const _Vb_const_iterator& _Right) const noexcept { + // test for compatible iterator pair #if _ITERATOR_DEBUG_LEVEL == 0 (void) _Right; #else // _ITERATOR_DEBUG_LEVEL == 0 -#ifdef __cpp_lib_constexpr_dynamic_alloc - if (!_STD is_constant_evaluated()) -#endif // __cpp_lib_constexpr_dynamic_alloc - { - _STL_VERIFY(this->_Getcont() == _Right._Getcont(), "vector iterators incompatible"); - } + _STL_VERIFY(this->_Getcont() == _Right._Getcont(), "vector iterators incompatible"); #endif // _ITERATOR_DEBUG_LEVEL } @@ -2255,14 +2124,9 @@ public: _CONSTEXPR20_CONTAINER void _Dec() noexcept { // decrement bit position #if _ITERATOR_DEBUG_LEVEL != 0 -#ifdef __cpp_lib_constexpr_dynamic_alloc - if (!_STD is_constant_evaluated()) -#endif // __cpp_lib_constexpr_dynamic_alloc - { - const auto _Cont = static_cast(this->_Getcont()); - _STL_VERIFY(_Cont, "cannot decrement value-initialized vector iterator"); - _STL_VERIFY(this->_Total_off(_Cont) > 0, "cannot decrement vector begin iterator"); - } + const auto _Cont = static_cast(this->_Getcont()); + _STL_VERIFY(_Cont, "cannot decrement value-initialized vector iterator"); + _STL_VERIFY(this->_Total_off(_Cont) > 0, "cannot decrement vector begin iterator"); #endif // _ITERATOR_DEBUG_LEVEL != 0 if (this->_Myoff != 0) { @@ -2275,15 +2139,10 @@ public: _CONSTEXPR20_CONTAINER void _Inc() noexcept { // increment bit position #if _ITERATOR_DEBUG_LEVEL != 0 -#ifdef __cpp_lib_constexpr_dynamic_alloc - if (!_STD is_constant_evaluated()) -#endif // __cpp_lib_constexpr_dynamic_alloc - { - const auto _Cont = static_cast(this->_Getcont()); - _STL_VERIFY(_Cont, "cannot increment value-initialized vector iterator"); - _STL_VERIFY(this->_Total_off(_Cont) < static_cast<_Difference_type>(_Cont->_Mysize), - "cannot increment vector end iterator"); - } + const auto _Cont = static_cast(this->_Getcont()); + _STL_VERIFY(_Cont, "cannot increment value-initialized vector iterator"); + _STL_VERIFY(this->_Total_off(_Cont) < static_cast<_Difference_type>(_Cont->_Mysize), + "cannot increment vector end iterator"); #endif // _ITERATOR_DEBUG_LEVEL != 0 if (this->_Myoff < _VBITS - 1) { @@ -2323,15 +2182,10 @@ public: _NODISCARD _CONSTEXPR20_CONTAINER reference operator*() const noexcept { #if _ITERATOR_DEBUG_LEVEL != 0 -#ifdef __cpp_lib_constexpr_dynamic_alloc - if (!_STD is_constant_evaluated()) -#endif // __cpp_lib_constexpr_dynamic_alloc - { - const auto _Cont = static_cast(this->_Getcont()); - _STL_VERIFY(_Cont, "cannot dereference value-initialized vector iterator"); - _STL_VERIFY(this->_Total_off(_Cont) < static_cast<_Difference_type>(_Cont->_Mysize), - "vector iterator not dereferenceable"); - } + const auto _Cont = static_cast(this->_Getcont()); + _STL_VERIFY(_Cont, "cannot dereference value-initialized vector iterator"); + _STL_VERIFY(this->_Total_off(_Cont) < static_cast<_Difference_type>(_Cont->_Mysize), + "vector iterator not dereferenceable"); #endif // _ITERATOR_DEBUG_LEVEL != 0 return _Reft(*this); diff --git a/stl/inc/xmemory b/stl/inc/xmemory index 5481f3ce40e..e227711b5be 100644 --- a/stl/inc/xmemory +++ b/stl/inc/xmemory @@ -1639,8 +1639,6 @@ _CONSTEXPR20_DYNALLOC _Alloc_ptr_t<_Alloc> _Uninitialized_copy( _Backout._Emplace_back(*_UFirst); } - _Dest = _Backout._Release(); - return _Backout._Release(); } diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index e7a7a9710e4..893be8074b9 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -1205,7 +1205,7 @@ #if defined(__cpp_constexpr_dynamic_alloc) && !defined(__clang__) // TRANSITION, LLVM-48606 #define __cpp_lib_constexpr_vector 201907L -#endif // __cpp_constexpr_dynamic_alloc && !__clang__ +#endif // defined(__cpp_constexpr_dynamic_alloc) && !defined(__clang__) #ifdef __cpp_impl_coroutine // TRANSITION, Clang coroutine support #define __cpp_lib_coroutine 201902L @@ -1289,7 +1289,7 @@ #endif // Functions that became constexpr in C++20 via P0980R1 or P1004R2 -#if defined(__cpp_lib_constexpr_dynamic_alloc) && !defined(__clang__) // TRANSITION:LLVM-48606 +#if defined(__cpp_lib_constexpr_dynamic_alloc) && !defined(__clang__) // TRANSITION, LLVM-48606 #define _CONSTEXPR20_CONTAINER constexpr #else #define _CONSTEXPR20_CONTAINER inline From aa3da7ba7b35fc2d3ec5228e382287b3f0448639 Mon Sep 17 00:00:00 2001 From: Miya Natsuhara Date: Fri, 5 Feb 2021 15:03:07 -0800 Subject: [PATCH 21/50] add more workarounds for VSO-1269037, VSO-1331017 --- stl/inc/vector | 9 ++++++++- stl/inc/xmemory | 4 ++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/stl/inc/vector b/stl/inc/vector index 46cb0186841..cd5938a7ec6 100644 --- a/stl/inc/vector +++ b/stl/inc/vector @@ -43,6 +43,9 @@ public: this->_Adopt(_Pvector); } + // TRANSITION, DevCom-1331017 + _CONSTEXPR20_CONTAINER _Vector_const_iterator& operator=(const _Vector_const_iterator&) = default; + _NODISCARD _CONSTEXPR20_CONTAINER reference operator*() const noexcept { #if _ITERATOR_DEBUG_LEVEL != 0 const auto _Mycont = static_cast(this->_Getcont()); @@ -250,6 +253,9 @@ public: using _Mybase::_Mybase; + // TRANSITION, DevCom-1331017 + _CONSTEXPR20_CONTAINER _Vector_iterator& operator=(const _Vector_iterator&) noexcept = default; + _NODISCARD _CONSTEXPR20_CONTAINER reference operator*() const noexcept { return const_cast(_Mybase::operator*()); } @@ -1767,7 +1773,8 @@ private: while (*_Pnext) { const auto _Pnextptr = static_cast(**_Pnext)._Ptr; if (_Pnextptr < _First || _Last < _Pnextptr) { // skip the iterator - _Pnext = &(*_Pnext)->_Mynextiter; + const auto _Temp = *_Pnext; // TRANSITION, VSO-1269037 + _Pnext = &_Temp->_Mynextiter; } else { // orphan the iterator (*_Pnext)->_Myproxy = nullptr; *_Pnext = (*_Pnext)->_Mynextiter; diff --git a/stl/inc/xmemory b/stl/inc/xmemory index e227711b5be..6b0e173e5b3 100644 --- a/stl/inc/xmemory +++ b/stl/inc/xmemory @@ -1212,8 +1212,8 @@ private: // MEMBER FUNCTIONS FOR _Container_base12 _CONSTEXPR20_CONTAINER void _Container_base12::_Orphan_all_unlocked() noexcept { - for (auto _Pnext = &_Myproxy->_Myfirstiter; *_Pnext; *_Pnext = (*_Pnext)->_Mynextiter) { - (*_Pnext)->_Myproxy = nullptr; + for (auto& _Pnext = _Myproxy->_Myfirstiter; _Pnext; _Pnext = (_Pnext)->_Mynextiter) { // TRANSITION, VSO-1269037 + _Pnext->_Myproxy = nullptr; } _Myproxy->_Myfirstiter = nullptr; } From eaf17a432bedcd6bb39833f764b7a13e4d64d43f Mon Sep 17 00:00:00 2001 From: Miya Natsuhara Date: Fri, 5 Feb 2021 15:57:20 -0800 Subject: [PATCH 22/50] xfail/skip libcxx tests triggered by VSO-1275530 --- tests/libcxx/expected_results.txt | 18 ++++++++++++++---- tests/libcxx/skipped_tests.txt | 16 +++++++++++++--- .../test.cpp | 2 ++ 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index e406827dbd4..64b2eafd82e 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -320,9 +320,6 @@ std/language.support/support.limits/support.limits.general/functional.version.pa std/language.support/support.limits/support.limits.general/iterator.version.pass.cpp FAIL std/language.support/support.limits/support.limits.general/memory.version.pass.cpp FAIL -# C++20 P1004R2 "constexpr std::vector" -std/language.support/support.limits/support.limits.general/vector.version.pass.cpp FAIL - # C++20 P1614R2 "Adding Spaceship <=> To The Library" std/language.support/support.limits/support.limits.general/compare.version.pass.cpp FAIL @@ -364,7 +361,7 @@ std/utilities/meta/meta.unary/meta.unary.prop/is_constructible.pass.cpp:0 FAIL std/containers/views/span.cons/ptr_len.pass.cpp:0 FAIL std/containers/views/span.cons/ptr_ptr.pass.cpp:0 FAIL -# VSO-1168723 "Implicit copy assignment incorrectly not constexpr when subobject has explicit constexpr copy constructor" +# VSO-1168723 "Implicit copy assignment `inc`orrectly not constexpr when subobject has explicit constexpr copy constructor" std/utilities/utility/pairs/pairs.pair/assign_pair.pass.cpp:0 FAIL std/utilities/utility/pairs/pairs.pair/assign_rv_pair.pass.cpp:0 FAIL std/utilities/utility/pairs/pairs.pair/assign_rv_pair_U_V.pass.cpp:0 FAIL @@ -373,6 +370,16 @@ std/utilities/utility/pairs/pairs.pair/assign_rv_pair_U_V.pass.cpp:0 FAIL std/algorithms/alg.sorting/alg.sort/partial.sort/partial_sort.pass.cpp:0 FAIL std/algorithms/alg.sorting/alg.sort/partial.sort/partial_sort_comp.pass.cpp:0 FAIL +# VSO-1275530 "[constexpr] Temporaries created for functions do not have a ctor called (and have a redundant dtor)." +std/numerics/numeric.ops/exclusive.scan/exclusive_scan.pass.cpp:0 FAIL +std/numerics/numeric.ops/exclusive.scan/exclusive_scan_init_op.pass.cpp:0 FAIL +std/numerics/numeric.ops/inclusive.scan/inclusive_scan.pass.cpp:0 FAIL +std/numerics/numeric.ops/inclusive.scan/inclusive_scan_op.pass.cpp:0 FAIL +std/numerics/numeric.ops/inclusive.scan/inclusive_scan_op_init.pass.cpp:0 FAIL +std/numerics/numeric.ops/transform.exclusive.scan/transform_exclusive_scan_init_bop_uop.pass.cpp:0 FAIL +std/numerics/numeric.ops/transform.inclusive.scan/transform_inclusive_scan_bop_uop.pass.cpp:0 FAIL +std/numerics/numeric.ops/transform.inclusive.scan/transform_inclusive_scan_bop_uop_init.pass.cpp:0 FAIL + # *** CLANG COMPILER BUGS *** # LLVM-33230 "Clang on Windows should define __STDCPP_THREADS__ to be 1" @@ -381,6 +388,9 @@ std/thread/macro.pass.cpp:1 FAIL # LLVM-46207 Clang's tgmath.h interferes with the UCRT's tgmath.h std/depr/depr.c.headers/tgmath_h.pass.cpp:1 FAIL +# LLVM-48606 "Clang rejects creation of struct with mutable member during constant evaluation" +language.support/support.limits/support.limits.general/vector.version.pass.cpp:1 FAIL + # *** CLANG ISSUES, NOT YET ANALYZED *** # Clang doesn't enable sized deallocation by default. Should we add -fsized-deallocation or do something else? diff --git a/tests/libcxx/skipped_tests.txt b/tests/libcxx/skipped_tests.txt index 9482df7db03..aa43293bfd5 100644 --- a/tests/libcxx/skipped_tests.txt +++ b/tests/libcxx/skipped_tests.txt @@ -320,9 +320,6 @@ language.support\support.limits\support.limits.general\functional.version.pass.c language.support\support.limits\support.limits.general\iterator.version.pass.cpp language.support\support.limits\support.limits.general\memory.version.pass.cpp -# C++20 P1004R2 "constexpr std::vector" -language.support\support.limits\support.limits.general\vector.version.pass.cpp - # C++20 P1614R2 "Adding Spaceship <=> To The Library" language.support\support.limits\support.limits.general\compare.version.pass.cpp @@ -373,6 +370,16 @@ utilities\utility\pairs\pairs.pair\assign_rv_pair_U_V.pass.cpp algorithms\alg.sorting\alg.sort\partial.sort\partial_sort.pass.cpp algorithms\alg.sorting\alg.sort\partial.sort\partial_sort_comp.pass.cpp +# VSO-1275530 "[constexpr] Temporaries created for functions do not have a ctor called (and have a redundant dtor)." +std\numerics\numeric.ops\exclusive.scan\exclusive_scan.pass.cpp +std\numerics\numeric.ops\exclusive.scan\exclusive_scan_init_op.pass.cpp +std\numerics\numeric.ops\inclusive.scan\inclusive_scan.pass.cpp +std\numerics\numeric.ops\inclusive.scan\inclusive_scan_op.pass.cpp +std\numerics\numeric.ops\inclusive.scan\inclusive_scan_op_init.pass.cpp +std\numerics\numeric.ops\transform.exclusive.scan\transform_exclusive_scan_init_bop_uop.pass.cpp +std\numerics\numeric.ops\transform.inclusive.scan\transform_inclusive_scan_bop_uop.pass.cpp +std\numerics\numeric.ops\transform.inclusive.scan\transform_inclusive_scan_bop_uop_init.pass.cpp + # *** CLANG COMPILER BUGS *** # LLVM-33230 "Clang on Windows should define __STDCPP_THREADS__ to be 1" @@ -381,6 +388,9 @@ thread\macro.pass.cpp # LLVM-46207 Clang's tgmath.h interferes with the UCRT's tgmath.h depr\depr.c.headers\tgmath_h.pass.cpp +# LLVM-48606 "Clang rejects creation of struct with mutable member during constant evaluation" +language.support\support\limits\support.limits.general\vector.version.pass.cpp + # *** CLANG ISSUES, NOT YET ANALYZED *** # Clang doesn't enable sized deallocation by default. Should we add -fsized-deallocation or do something else? diff --git a/tests/std/tests/Dev10_816787_swap_vector_bool_elements/test.cpp b/tests/std/tests/Dev10_816787_swap_vector_bool_elements/test.cpp index 49726a50d6c..619ccd9a0f0 100644 --- a/tests/std/tests/Dev10_816787_swap_vector_bool_elements/test.cpp +++ b/tests/std/tests/Dev10_816787_swap_vector_bool_elements/test.cpp @@ -17,6 +17,7 @@ int main() { assert(all_of(x.begin(), x.end(), is_false)); assert(all_of(y.begin(), y.end(), is_true)); +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273381 swap(x[12], y[34]); assert(all_of(x.begin(), x.begin() + 12, is_false)); @@ -26,4 +27,5 @@ int main() { assert(all_of(y.begin(), y.begin() + 34, is_true)); assert(!y[34]); assert(all_of(y.begin() + 35, y.end(), is_true)); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 } From e2d23ea35710378fff31e3cdf829690df2d2039a Mon Sep 17 00:00:00 2001 From: Miya Natsuhara Date: Fri, 5 Feb 2021 16:07:20 -0800 Subject: [PATCH 23/50] update transition comments with new bug number --- tests/std/tests/P1004R2_constexpr_vector/test.cpp | 14 +++++++++----- .../tests/P1004R2_constexpr_vector_bool/test.cpp | 9 ++++++--- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/tests/std/tests/P1004R2_constexpr_vector/test.cpp b/tests/std/tests/P1004R2_constexpr_vector/test.cpp index 40ef1e37a7c..4f79104ffd5 100644 --- a/tests/std/tests/P1004R2_constexpr_vector/test.cpp +++ b/tests/std/tests/P1004R2_constexpr_vector/test.cpp @@ -9,7 +9,8 @@ using namespace std; -#if defined(MSVC_INTERNAL_TESTING) || defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1270433 +#if defined(MSVC_INTERNAL_TESTING) || defined(__EDG__) \ + || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1270433, VSO-1275530 static constexpr int input[] = {0, 1, 2, 3, 4, 5}; #endif // defined(MSVC_INTERNAL_TESTING) || defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 @@ -65,7 +66,8 @@ struct soccc_allocator { using vec = vector>; _CONSTEXPR20_CONTAINER bool test_interface() { -#if defined(MSVC_INTERNAL_TESTING) || defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1270433 +#if defined(MSVC_INTERNAL_TESTING) || defined(__EDG__) \ + || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1270433, VSO-1275530 { // constructors // Non allocator constructors @@ -487,7 +489,8 @@ _CONSTEXPR20_CONTAINER bool test_interface() { } _CONSTEXPR20_CONTAINER bool test_iterators() { -#if defined(MSVC_INTERNAL_TESTING) || defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1270433 +#if defined(MSVC_INTERNAL_TESTING) || defined(__EDG__) \ + || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1270433, VSO-1275530 vec range_constructed(begin(input), end(input)); #if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273381 @@ -587,7 +590,8 @@ _CONSTEXPR20_CONTAINER bool test_iterators() { } _CONSTEXPR20_CONTAINER bool test_growth() { -#if defined(MSVC_INTERNAL_TESTING) || defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1270433 +#if defined(MSVC_INTERNAL_TESTING) || defined(__EDG__) \ + || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1270433, VSO-1275530 { vector v(1000, 1729); @@ -683,7 +687,7 @@ _CONSTEXPR20_CONTAINER bool test_growth() { assert(v.capacity() == 8000); #endif // __EDG__ } -#endif // defined(MSVC_INTERNAL_CHECKING) || defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 +#endif // defined(_MSVC_INTERNAL_TESTING) || defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 return true; } diff --git a/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp b/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp index 964cc522ab6..f8f87901de4 100644 --- a/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp +++ b/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp @@ -9,7 +9,8 @@ using namespace std; -#if defined(MSVC_INTERNAL_TESTING) || defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1270433 +#if defined(MSVC_INTERNAL_TESTING) || defined(__EDG__) \ + || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1270433, VSO-1275530 static constexpr bool input[] = {true, false, true, true, false, true}; #endif // defined(MSVC_INTERNAL_TESTING) || defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 @@ -65,7 +66,8 @@ struct soccc_allocator { using vec = vector>; _CONSTEXPR20_CONTAINER bool test_interface() { -#if defined(MSVC_INTERNAL_TESTING) || defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1270433 +#if defined(MSVC_INTERNAL_TESTING) || defined(__EDG__) \ + || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1270433, VSO-1275530 { // constructors // Non allocator constructors @@ -500,7 +502,8 @@ _CONSTEXPR20_CONTAINER bool test_interface() { } _CONSTEXPR20_CONTAINER bool test_iterators() { -#if defined(MSVC_INTERNAL_TESTING) || defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1270433 +#if defined(MSVC_INTERNAL_TESTING) || defined(__EDG__) \ + || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1270433, VSO-1275530 #ifndef __EDG__ // TRANSITION, VSO-1274387 vec range_constructed(begin(input), end(input)); From 06a77720ce368af077b6e4e9ace52152ca210c02 Mon Sep 17 00:00:00 2001 From: Miya Natsuhara Date: Fri, 5 Feb 2021 16:39:17 -0800 Subject: [PATCH 24/50] fix formatting in expected_results/skipped_tests --- tests/libcxx/expected_results.txt | 4 ++-- tests/libcxx/skipped_tests.txt | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index 64b2eafd82e..5afeb945ccb 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -361,7 +361,7 @@ std/utilities/meta/meta.unary/meta.unary.prop/is_constructible.pass.cpp:0 FAIL std/containers/views/span.cons/ptr_len.pass.cpp:0 FAIL std/containers/views/span.cons/ptr_ptr.pass.cpp:0 FAIL -# VSO-1168723 "Implicit copy assignment `inc`orrectly not constexpr when subobject has explicit constexpr copy constructor" +# VSO-1168723 "Implicit copy assignment incorrectly not constexpr when subobject has explicit constexpr copy constructor" std/utilities/utility/pairs/pairs.pair/assign_pair.pass.cpp:0 FAIL std/utilities/utility/pairs/pairs.pair/assign_rv_pair.pass.cpp:0 FAIL std/utilities/utility/pairs/pairs.pair/assign_rv_pair_U_V.pass.cpp:0 FAIL @@ -389,7 +389,7 @@ std/thread/macro.pass.cpp:1 FAIL std/depr/depr.c.headers/tgmath_h.pass.cpp:1 FAIL # LLVM-48606 "Clang rejects creation of struct with mutable member during constant evaluation" -language.support/support.limits/support.limits.general/vector.version.pass.cpp:1 FAIL +std/language.support/support.limits/support.limits.general/vector.version.pass.cpp:1 FAIL # *** CLANG ISSUES, NOT YET ANALYZED *** diff --git a/tests/libcxx/skipped_tests.txt b/tests/libcxx/skipped_tests.txt index aa43293bfd5..5fe19e8f505 100644 --- a/tests/libcxx/skipped_tests.txt +++ b/tests/libcxx/skipped_tests.txt @@ -371,14 +371,14 @@ algorithms\alg.sorting\alg.sort\partial.sort\partial_sort.pass.cpp algorithms\alg.sorting\alg.sort\partial.sort\partial_sort_comp.pass.cpp # VSO-1275530 "[constexpr] Temporaries created for functions do not have a ctor called (and have a redundant dtor)." -std\numerics\numeric.ops\exclusive.scan\exclusive_scan.pass.cpp -std\numerics\numeric.ops\exclusive.scan\exclusive_scan_init_op.pass.cpp -std\numerics\numeric.ops\inclusive.scan\inclusive_scan.pass.cpp -std\numerics\numeric.ops\inclusive.scan\inclusive_scan_op.pass.cpp -std\numerics\numeric.ops\inclusive.scan\inclusive_scan_op_init.pass.cpp -std\numerics\numeric.ops\transform.exclusive.scan\transform_exclusive_scan_init_bop_uop.pass.cpp -std\numerics\numeric.ops\transform.inclusive.scan\transform_inclusive_scan_bop_uop.pass.cpp -std\numerics\numeric.ops\transform.inclusive.scan\transform_inclusive_scan_bop_uop_init.pass.cpp +numerics\numeric.ops\exclusive.scan\exclusive_scan.pass.cpp +numerics\numeric.ops\exclusive.scan\exclusive_scan_init_op.pass.cpp +numerics\numeric.ops\inclusive.scan\inclusive_scan.pass.cpp +numerics\numeric.ops\inclusive.scan\inclusive_scan_op.pass.cpp +numerics\numeric.ops\inclusive.scan\inclusive_scan_op_init.pass.cpp +numerics\numeric.ops\transform.exclusive.scan\transform_exclusive_scan_init_bop_uop.pass.cpp +numerics\numeric.ops\transform.inclusive.scan\transform_inclusive_scan_bop_uop.pass.cpp +numerics\numeric.ops\transform.inclusive.scan\transform_inclusive_scan_bop_uop_init.pass.cpp # *** CLANG COMPILER BUGS *** From ac012b67ee815464586227972c9504362296bea9 Mon Sep 17 00:00:00 2001 From: Miya Natsuhara Date: Fri, 5 Feb 2021 18:29:41 -0800 Subject: [PATCH 25/50] add missing test coverage --- .../tests/P1004R2_constexpr_vector/test.cpp | 11 ++++++++++- .../P1004R2_constexpr_vector_bool/test.cpp | 18 +++++++++++++++++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/tests/std/tests/P1004R2_constexpr_vector/test.cpp b/tests/std/tests/P1004R2_constexpr_vector/test.cpp index 4f79104ffd5..fd235e45a44 100644 --- a/tests/std/tests/P1004R2_constexpr_vector/test.cpp +++ b/tests/std/tests/P1004R2_constexpr_vector/test.cpp @@ -412,6 +412,9 @@ _CONSTEXPR20_CONTAINER bool test_interface() { inserted.insert(inserted.cbegin(), {2, 3, 4}); assert(inserted.size() == 22); + inserted.insert(inserted.begin(), 4, 11); + assert(inserted.size() == 26); + vec emplaced; emplaced.emplace(emplaced.cbegin(), 42); assert(emplaced.size() == 1); @@ -441,7 +444,13 @@ _CONSTEXPR20_CONTAINER bool test_interface() { emplaced.swap(inserted); assert(inserted.size() == 1); assert(inserted.front() == 42); - assert(emplaced.size() == 22); + assert(emplaced.size() == 26); + + emplaced.erase(emplaced.end() - 1); + assert(emplaced.size() == 25); + + emplaced.erase(emplaced.begin(), emplaced.begin() + 2); + assert(emplaced.size() == 23); #endif // __EDG__ } diff --git a/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp b/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp index f8f87901de4..711469452a9 100644 --- a/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp +++ b/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp @@ -11,7 +11,8 @@ using namespace std; #if defined(MSVC_INTERNAL_TESTING) || defined(__EDG__) \ || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1270433, VSO-1275530 -static constexpr bool input[] = {true, false, true, true, false, true}; +static constexpr bool input[] = {true, false, true, true, false, true}; +static constexpr bool input_flipped[] = {false, true, false, false, true, false}; #endif // defined(MSVC_INTERNAL_TESTING) || defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 template @@ -379,6 +380,12 @@ _CONSTEXPR20_CONTAINER bool test_interface() { #ifndef __EDG__ // TRANSITION, VSO-1274387 vec range_constructed(begin(input), end(input)); + vec flipped = range_constructed; + flipped.flip(); + assert(flipped.size() == 6); + assert(equal(flipped.begin(), flipped.end(), begin(input_flipped), end(input_flipped))); + // {true, false, true, true, false, true}; + vec cleared = range_constructed; cleared.clear(); assert(cleared.empty()); @@ -421,6 +428,9 @@ _CONSTEXPR20_CONTAINER bool test_interface() { inserted.insert(inserted.cbegin(), {false, true, false}); assert(inserted.size() == 22); + inserted.insert(inserted.cbegin(), 3, true); + assert(inserted.size() == 25); + vec emplaced; emplaced.emplace(emplaced.cbegin(), false); assert(emplaced.size() == 1); @@ -450,6 +460,12 @@ _CONSTEXPR20_CONTAINER bool test_interface() { emplaced.swap(inserted); assert(inserted.size() == 1); assert(inserted.front() == false); + assert(emplaced.size() == 25); + + emplaced.erase(emplaced.end() - 1); + assert(emplaced.size() == 24); + + emplaced.erase(emplaced.begin(), emplaced.begin() + 2); assert(emplaced.size() == 22); #endif // __EDG__ } From e11cd62998e50327366e2b92a495f63c5cf81b56 Mon Sep 17 00:00:00 2001 From: Miya Natsuhara Date: Mon, 8 Feb 2021 11:23:32 -0800 Subject: [PATCH 26/50] Fix regex _Orphan_me* call --- stl/inc/regex | 2 +- stl/inc/xmemory | 32 ++++++++++++++++---------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/stl/inc/regex b/stl/inc/regex index 330944b8a28..f42d74e9708 100644 --- a/stl/inc/regex +++ b/stl/inc/regex @@ -2466,7 +2466,7 @@ public: _MyRe = nullptr; #if _ITERATOR_DEBUG_LEVEL == 2 - this->_Orphan_me_v2(); + this->_Orphan_me_unlocked(); #endif // _ITERATOR_DEBUG_LEVEL return *this; diff --git a/stl/inc/xmemory b/stl/inc/xmemory index 6b0e173e5b3..3ace7de7b93 100644 --- a/stl/inc/xmemory +++ b/stl/inc/xmemory @@ -1175,22 +1175,6 @@ public: _Container_proxy* _Myproxy = nullptr; _Iterator_base12* _Mynextiter = nullptr; -#if _ITERATOR_DEBUG_LEVEL == 2 -private: - _CONSTEXPR20_CONTAINER void _Adopt_unlocked(_Container_proxy* _Parent_proxy) noexcept { - if (_Myproxy) { // adopted, remove self from list - _Orphan_me_unlocked(); - } - _Mynextiter = _Parent_proxy->_Myfirstiter; - _Parent_proxy->_Myfirstiter = this; - _Myproxy = _Parent_proxy; - } - - void _Adopt_locked(_Container_proxy* _Parent_proxy) noexcept { - _Lockit _Lock(_LOCK_DEBUG); - _Adopt_unlocked(_Parent_proxy); - } - _CONSTEXPR20_CONTAINER void _Orphan_me_unlocked() noexcept { _Iterator_base12** _Pnext = &_Myproxy->_Myfirstiter; while (*_Pnext && *_Pnext != this) { @@ -1207,6 +1191,22 @@ private: _Lockit _Lock(_LOCK_DEBUG); _Orphan_me_unlocked(); } + +#if _ITERATOR_DEBUG_LEVEL == 2 +private: + _CONSTEXPR20_CONTAINER void _Adopt_unlocked(_Container_proxy* _Parent_proxy) noexcept { + if (_Myproxy) { // adopted, remove self from list + _Orphan_me_unlocked(); + } + _Mynextiter = _Parent_proxy->_Myfirstiter; + _Parent_proxy->_Myfirstiter = this; + _Myproxy = _Parent_proxy; + } + + void _Adopt_locked(_Container_proxy* _Parent_proxy) noexcept { + _Lockit _Lock(_LOCK_DEBUG); + _Adopt_unlocked(_Parent_proxy); + } #endif // _ITERATOR_DEBUG_LEVEL == 2 }; From ad545c019917cf1c41bf8dbf50f2deef9052e655 Mon Sep 17 00:00:00 2001 From: Miya Natsuhara Date: Mon, 8 Feb 2021 13:43:24 -0800 Subject: [PATCH 27/50] remove defined(_MSVC_INTERNAL_TESTING) until tests are passing internally --- .../tests/P1004R2_constexpr_vector/test.cpp | 24 +++++++++---------- .../P1004R2_constexpr_vector_bool/test.cpp | 12 +++++----- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/tests/std/tests/P1004R2_constexpr_vector/test.cpp b/tests/std/tests/P1004R2_constexpr_vector/test.cpp index fd235e45a44..daf2f890990 100644 --- a/tests/std/tests/P1004R2_constexpr_vector/test.cpp +++ b/tests/std/tests/P1004R2_constexpr_vector/test.cpp @@ -9,10 +9,10 @@ using namespace std; -#if defined(MSVC_INTERNAL_TESTING) || defined(__EDG__) \ - || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1270433, VSO-1275530 +#if defined(__EDG__) \ + || _ITERATOR_DEBUG_LEVEL != 2 // || defined(MSVC_INTERNAL_TESTING) // TRANSITION, VSO-1270433, VSO-1275530 static constexpr int input[] = {0, 1, 2, 3, 4, 5}; -#endif // defined(MSVC_INTERNAL_TESTING) || defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 +#endif // defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 || defined(MSVC_INTERNAL_TESTING) template struct soccc_allocator { @@ -66,8 +66,8 @@ struct soccc_allocator { using vec = vector>; _CONSTEXPR20_CONTAINER bool test_interface() { -#if defined(MSVC_INTERNAL_TESTING) || defined(__EDG__) \ - || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1270433, VSO-1275530 +#if defined(__EDG__) \ + || _ITERATOR_DEBUG_LEVEL != 2 // || defined(MSVC_INTERNAL_TESTING) // TRANSITION, VSO-1270433, VSO-1275530 { // constructors // Non allocator constructors @@ -493,13 +493,13 @@ _CONSTEXPR20_CONTAINER bool test_interface() { static_assert(is_same_v, bool>); assert(ne); } -#endif // defined(MSVC_INTERNAL_TESTING) || defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 +#endif // defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 || defined(MSVC_INTERNAL_TESTING) return true; } _CONSTEXPR20_CONTAINER bool test_iterators() { -#if defined(MSVC_INTERNAL_TESTING) || defined(__EDG__) \ - || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1270433, VSO-1275530 +#if defined(__EDG__) \ + || _ITERATOR_DEBUG_LEVEL != 2 // || defined(MSVC_INTERNAL_TESTING) // TRANSITION, VSO-1270433, VSO-1275530 vec range_constructed(begin(input), end(input)); #if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273381 @@ -594,13 +594,13 @@ _CONSTEXPR20_CONTAINER bool test_iterators() { } #endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 -#endif // defined(MSVC_INTERNAL_TESTING) || defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 +#endif // defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 || defined(MSVC_INTERNAL_TESTING) return true; } _CONSTEXPR20_CONTAINER bool test_growth() { -#if defined(MSVC_INTERNAL_TESTING) || defined(__EDG__) \ - || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1270433, VSO-1275530 +#if defined(__EDG__) \ + || _ITERATOR_DEBUG_LEVEL != 2 // || defined(MSVC_INTERNAL_TESTING) // TRANSITION, VSO-1270433, VSO-1275530 { vector v(1000, 1729); @@ -696,7 +696,7 @@ _CONSTEXPR20_CONTAINER bool test_growth() { assert(v.capacity() == 8000); #endif // __EDG__ } -#endif // defined(_MSVC_INTERNAL_TESTING) || defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 +#endif // defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 || defined(MSVC_INTERNAL_TESTING) return true; } diff --git a/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp b/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp index 711469452a9..838d711e879 100644 --- a/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp +++ b/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp @@ -67,8 +67,8 @@ struct soccc_allocator { using vec = vector>; _CONSTEXPR20_CONTAINER bool test_interface() { -#if defined(MSVC_INTERNAL_TESTING) || defined(__EDG__) \ - || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1270433, VSO-1275530 +#if defined(__EDG__) \ + || _ITERATOR_DEBUG_LEVEL != 2 // || defined(_MSVC_INTERNAL_TESTING) // TRANSITION, VSO-1270433, VSO-1275530 { // constructors // Non allocator constructors @@ -512,14 +512,14 @@ _CONSTEXPR20_CONTAINER bool test_interface() { assert(ne); #endif // __EDG__ } -#endif // defined(MSVC_INTERNAL_TESTING) || defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 +#endif // defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 || defined(MSVC_INTERNAL_TESTING) return true; } _CONSTEXPR20_CONTAINER bool test_iterators() { -#if defined(MSVC_INTERNAL_TESTING) || defined(__EDG__) \ - || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1270433, VSO-1275530 +#if defined(__EDG__) \ + || _ITERATOR_DEBUG_LEVEL != 2 // || defined(_MSVC_INTERNAL_TESTING) // TRANSITION, VSO-1270433, VSO-1275530 #ifndef __EDG__ // TRANSITION, VSO-1274387 vec range_constructed(begin(input), end(input)); @@ -615,7 +615,7 @@ _CONSTEXPR20_CONTAINER bool test_iterators() { } #endif // __EDG__ #endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 -#endif // defined(MSVC_INTERNAL_TESTING) || defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 +#endif // defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 || defined(MSVC_INTERNAL_TESTING) return true; } From 25dba613bb4dfb5ad5e56dc4a8d2312a08a3dd65 Mon Sep 17 00:00:00 2001 From: Miya Natsuhara Date: Mon, 8 Feb 2021 14:54:11 -0800 Subject: [PATCH 28/50] Fix up tests with recent changes to constexpr containers status, new bug --- tests/std/tests/P0784R7_library_machinery/test.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/std/tests/P0784R7_library_machinery/test.cpp b/tests/std/tests/P0784R7_library_machinery/test.cpp index b5dd430f7c5..6e207bf38c0 100644 --- a/tests/std/tests/P0784R7_library_machinery/test.cpp +++ b/tests/std/tests/P0784R7_library_machinery/test.cpp @@ -50,7 +50,7 @@ static constexpr int_wrapper_copy expected_copy[] = {1, 2, 3, 4}; static constexpr int_wrapper_move expected_move[] = {1, 2, 3, 4}; static constexpr int_wrapper_move expected_after_move[] = {-1, -1, -1, -1}; -constexpr bool test() { +_CONSTEXPR20_DYNALLOC bool test() { { // _Copy_unchecked int_wrapper_copy input[] = {1, 2, 3, 4}; int_wrapper_copy output[4] = {5, 6, 7, 8}; @@ -71,7 +71,7 @@ constexpr bool test() { assert(equal(begin(expected_copy), end(expected_copy), begin(output), end(output))); } -#if _HAS_CXX20 && defined(__cpp_constexpr_dynamic_alloc) && defined(__clang__) +#if _HAS_CXX20 && defined(__cpp_constexpr_dynamic_alloc) { // _Uninitialized_copy_unchecked int_wrapper_copy input[] = {1, 2, 3, 4}; int_wrapper_copy output[4]; @@ -124,7 +124,8 @@ constexpr bool test() { } #endif // __cpp_lib_concepts -#if _HAS_CXX20 && defined(__cpp_constexpr_dynamic_alloc) && defined(__clang__) +#if _HAS_CXX20 && defined(__cpp_constexpr_dynamic_alloc) \ + && (defined(__clang__) || defined(__EDG__)) // TRANSITION, DevCom-1333853 { // _Uninitialized_move_unchecked int_wrapper_move input[] = {1, 2, 3, 4}; int_wrapper_move output[4]; From 525847c3bf6e387f34ac2098b7965249b79d59b3 Mon Sep 17 00:00:00 2001 From: Miya Natsuhara Date: Mon, 8 Feb 2021 15:08:39 -0800 Subject: [PATCH 29/50] update #endif comment to match --- tests/std/tests/P0784R7_library_machinery/test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/std/tests/P0784R7_library_machinery/test.cpp b/tests/std/tests/P0784R7_library_machinery/test.cpp index 6e207bf38c0..a5fa168550b 100644 --- a/tests/std/tests/P0784R7_library_machinery/test.cpp +++ b/tests/std/tests/P0784R7_library_machinery/test.cpp @@ -138,7 +138,7 @@ _CONSTEXPR20_DYNALLOC bool test() { assert(equal(begin(input), end(input), begin(expected_after_move), end(expected_after_move))); } } -#endif // _HAS_CXX20 && defined(__cpp_constexpr_dynamic_alloc) +#endif // _HAS_CXX20 && defined(__cpp_constexpr_dynamic_alloc) && (defined(__clang__) || defined(__EDG__)) return true; } From 95fc807b672f2b5d623ae2a6aec880cbbfe67759 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 9 Feb 2021 23:26:01 -0800 Subject: [PATCH 30/50] Test addition: Feature-test macro. --- .../test.compile.pass.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp index b0f604ebbca..f4ab60d8fcc 100644 --- a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp +++ b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp @@ -523,6 +523,20 @@ STATIC_ASSERT(__cpp_lib_constexpr_utility == 201811L); #endif #endif +#if _HAS_CXX20 && defined(__cpp_constexpr_dynamic_alloc) && !defined(__clang__) // TRANSITION, LLVM-48606 +#ifndef __cpp_lib_constexpr_vector +#error __cpp_lib_constexpr_vector is not defined +#elif __cpp_lib_constexpr_vector != 201907L +#error __cpp_lib_constexpr_vector is not 201907L +#else +STATIC_ASSERT(__cpp_lib_constexpr_vector == 201907L); +#endif +#else +#ifdef __cpp_lib_constexpr_vector +#error __cpp_lib_constexpr_vector is defined +#endif +#endif + #if _HAS_CXX20 && defined(__cpp_impl_coroutine) // TRANSITION, Clang coroutine support #ifndef __cpp_lib_coroutine #error __cpp_lib_coroutine is not defined From 93512204b706b3a9a2841bec383ba7ef388e5e00 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 11 Feb 2021 04:06:54 -0800 Subject: [PATCH 31/50] cleanups: Add noexcept consistently, detach comment. --- stl/inc/vector | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stl/inc/vector b/stl/inc/vector index cd5938a7ec6..c5740fe9bfe 100644 --- a/stl/inc/vector +++ b/stl/inc/vector @@ -44,7 +44,7 @@ public: } // TRANSITION, DevCom-1331017 - _CONSTEXPR20_CONTAINER _Vector_const_iterator& operator=(const _Vector_const_iterator&) = default; + _CONSTEXPR20_CONTAINER _Vector_const_iterator& operator=(const _Vector_const_iterator&) noexcept = default; _NODISCARD _CONSTEXPR20_CONTAINER reference operator*() const noexcept { #if _ITERATOR_DEBUG_LEVEL != 0 @@ -745,8 +745,8 @@ public: emplace_back(_Val); } - _CONSTEXPR20_CONTAINER void push_back( - _Ty&& _Val) { // insert by moving into element at end, provide strong guarantee + _CONSTEXPR20_CONTAINER void push_back(_Ty&& _Val) { + // insert by moving into element at end, provide strong guarantee emplace_back(_STD move(_Val)); } From 359de1df1a6bffa1915cea1a624a234bf22e5307 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 11 Feb 2021 04:08:17 -0800 Subject: [PATCH 32/50] cleanups: Remove unnecessary parentheses, add newline. --- stl/inc/xmemory | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stl/inc/xmemory b/stl/inc/xmemory index 3ace7de7b93..ae7b0773dfa 100644 --- a/stl/inc/xmemory +++ b/stl/inc/xmemory @@ -1212,7 +1212,7 @@ private: // MEMBER FUNCTIONS FOR _Container_base12 _CONSTEXPR20_CONTAINER void _Container_base12::_Orphan_all_unlocked() noexcept { - for (auto& _Pnext = _Myproxy->_Myfirstiter; _Pnext; _Pnext = (_Pnext)->_Mynextiter) { // TRANSITION, VSO-1269037 + for (auto& _Pnext = _Myproxy->_Myfirstiter; _Pnext; _Pnext = _Pnext->_Mynextiter) { // TRANSITION, VSO-1269037 _Pnext->_Myproxy = nullptr; } _Myproxy->_Myfirstiter = nullptr; @@ -1634,6 +1634,7 @@ _CONSTEXPR20_DYNALLOC _Alloc_ptr_t<_Alloc> _Uninitialized_copy( return _Dest; } } + _Uninitialized_backout_al<_Alloc> _Backout{_Dest, _Al}; for (; _UFirst != _ULast; ++_UFirst) { _Backout._Emplace_back(*_UFirst); From 9ce6e1659dcd81fcd1aa7ece2e36200dae470cd6 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 10 Feb 2021 00:05:05 -0800 Subject: [PATCH 33/50] , : Undo incorrect/unnecessary orphaning changes. --- stl/inc/regex | 2 +- stl/inc/xmemory | 32 ++++++++++++++++---------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/stl/inc/regex b/stl/inc/regex index f42d74e9708..330944b8a28 100644 --- a/stl/inc/regex +++ b/stl/inc/regex @@ -2466,7 +2466,7 @@ public: _MyRe = nullptr; #if _ITERATOR_DEBUG_LEVEL == 2 - this->_Orphan_me_unlocked(); + this->_Orphan_me_v2(); #endif // _ITERATOR_DEBUG_LEVEL return *this; diff --git a/stl/inc/xmemory b/stl/inc/xmemory index ae7b0773dfa..c3fdd774d14 100644 --- a/stl/inc/xmemory +++ b/stl/inc/xmemory @@ -1175,6 +1175,22 @@ public: _Container_proxy* _Myproxy = nullptr; _Iterator_base12* _Mynextiter = nullptr; +#if _ITERATOR_DEBUG_LEVEL == 2 +private: + _CONSTEXPR20_CONTAINER void _Adopt_unlocked(_Container_proxy* _Parent_proxy) noexcept { + if (_Myproxy) { // adopted, remove self from list + _Orphan_me_unlocked(); + } + _Mynextiter = _Parent_proxy->_Myfirstiter; + _Parent_proxy->_Myfirstiter = this; + _Myproxy = _Parent_proxy; + } + + void _Adopt_locked(_Container_proxy* _Parent_proxy) noexcept { + _Lockit _Lock(_LOCK_DEBUG); + _Adopt_unlocked(_Parent_proxy); + } + _CONSTEXPR20_CONTAINER void _Orphan_me_unlocked() noexcept { _Iterator_base12** _Pnext = &_Myproxy->_Myfirstiter; while (*_Pnext && *_Pnext != this) { @@ -1191,22 +1207,6 @@ public: _Lockit _Lock(_LOCK_DEBUG); _Orphan_me_unlocked(); } - -#if _ITERATOR_DEBUG_LEVEL == 2 -private: - _CONSTEXPR20_CONTAINER void _Adopt_unlocked(_Container_proxy* _Parent_proxy) noexcept { - if (_Myproxy) { // adopted, remove self from list - _Orphan_me_unlocked(); - } - _Mynextiter = _Parent_proxy->_Myfirstiter; - _Parent_proxy->_Myfirstiter = this; - _Myproxy = _Parent_proxy; - } - - void _Adopt_locked(_Container_proxy* _Parent_proxy) noexcept { - _Lockit _Lock(_LOCK_DEBUG); - _Adopt_unlocked(_Parent_proxy); - } #endif // _ITERATOR_DEBUG_LEVEL == 2 }; From c8e63416d480abbc7d5ad9f7bcfe4acf56d84679 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 11 Feb 2021 02:13:14 -0800 Subject: [PATCH 34/50] : Guard _Check_all_orphaned identically to its usage. --- stl/inc/vector | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/vector b/stl/inc/vector index c5740fe9bfe..5268973a2e8 100644 --- a/stl/inc/vector +++ b/stl/inc/vector @@ -1305,7 +1305,7 @@ private: _Change_array(_Newvec, _Size, _Newcapacity); } -#if _ITERATOR_DEBUG_LEVEL != 0 +#if _ITERATOR_DEBUG_LEVEL != 0 && defined(_ENABLE_STL_INTERNAL_CHECK) void _Check_all_orphaned_locked() const noexcept { _Lockit _Lock(_LOCK_DEBUG); auto& _My_data = _Mypair._Myval2; @@ -1323,7 +1323,7 @@ private: _Check_all_orphaned_locked(); } } -#endif // _ITERATOR_DEBUG_LEVEL != 0 +#endif // _ITERATOR_DEBUG_LEVEL != 0 && defined(_ENABLE_STL_INTERNAL_CHECK) _CONSTEXPR20_CONTAINER void _Clear_and_reserve_geometric(const size_type _Newsize) { auto& _My_data = _Mypair._Myval2; From 4f334f05e36ab125468b2e3394dc7c563585148f Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 11 Feb 2021 02:14:42 -0800 Subject: [PATCH 35/50] : hash for vector can't be constexpr, and doesn't need to be. --- stl/inc/vector | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/vector b/stl/inc/vector index 5268973a2e8..1d6143bff3d 100644 --- a/stl/inc/vector +++ b/stl/inc/vector @@ -2969,7 +2969,7 @@ struct hash> { _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef vector _ARGUMENT_TYPE_NAME; _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef size_t _RESULT_TYPE_NAME; - _NODISCARD _CONSTEXPR20_CONTAINER size_t operator()(const vector& _Keyval) const noexcept { + _NODISCARD size_t operator()(const vector& _Keyval) const noexcept { return _Hash_array_representation(_Keyval._Myvec.data(), _Keyval._Myvec.size()); } }; From c7122592e63f3e3003232cecf4c2697e2db78072 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 11 Feb 2021 04:17:55 -0800 Subject: [PATCH 36/50] Test cleanup: Drop std qualification. --- .../tests/P1004R2_constexpr_vector/test.cpp | 16 ++++++++-------- .../P1004R2_constexpr_vector_bool/test.cpp | 18 +++++++++--------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/tests/std/tests/P1004R2_constexpr_vector/test.cpp b/tests/std/tests/P1004R2_constexpr_vector/test.cpp index daf2f890990..12362af2964 100644 --- a/tests/std/tests/P1004R2_constexpr_vector/test.cpp +++ b/tests/std/tests/P1004R2_constexpr_vector/test.cpp @@ -56,7 +56,7 @@ struct soccc_allocator { template _CONSTEXPR20_CONTAINER void construct(T* const p, Args&&... args) { - construct_at(p, std::forward(args)...); + construct_at(p, forward(args)...); } int id = 0; @@ -117,7 +117,7 @@ _CONSTEXPR20_CONTAINER bool test_interface() { assert(equal(copy_assigned.begin(), copy_assigned.end(), range_constructed.begin(), range_constructed.end())); #endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 - vec move_assigned = std::move(copy_assigned); + vec move_assigned = move(copy_assigned); #if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1274387 assert(equal(move_assigned.begin(), move_assigned.end(), range_constructed.begin(), range_constructed.end())); #endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 @@ -344,23 +344,23 @@ _CONSTEXPR20_CONTAINER bool test_interface() { assert(!e); const auto s = range_constructed.size(); - static_assert(is_same_v, std::size_t>); + static_assert(is_same_v, size_t>); assert(s == size(input)); const auto ms = range_constructed.max_size(); - static_assert(is_same_v, std::size_t>); + static_assert(is_same_v, size_t>); assert(ms == static_cast(-1) / 4); range_constructed.reserve(20); const auto c = range_constructed.capacity(); - static_assert(is_same_v, std::size_t>); + static_assert(is_same_v, size_t>); assert(c == 20); range_constructed.shrink_to_fit(); const auto c2 = range_constructed.capacity(); - static_assert(is_same_v, std::size_t>); + static_assert(is_same_v, size_t>); assert(c2 == 6); } @@ -585,8 +585,8 @@ _CONSTEXPR20_CONTAINER bool test_iterators() { const auto cit = range_constructed.cbegin() + 2; assert(cit[2] == 3); - std::vector> vec2 = {{1, 2}, {2, 3}}; - const auto it2 = vec2.begin(); + vector> vec2 = {{1, 2}, {2, 3}}; + const auto it2 = vec2.begin(); assert(it2->second == 2); const auto cit2 = vec2.cbegin(); diff --git a/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp b/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp index 838d711e879..15728c7d6b1 100644 --- a/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp +++ b/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp @@ -57,7 +57,7 @@ struct soccc_allocator { template _CONSTEXPR20_DYNALLOC void construct(T* const p, Args&&... args) { - construct_at(p, std::forward(args)...); + construct_at(p, forward(args)...); } int id = 0; @@ -123,7 +123,7 @@ _CONSTEXPR20_CONTAINER bool test_interface() { vec copy_assigned = range_constructed; assert(equal(copy_assigned.begin(), copy_assigned.end(), range_constructed.begin(), range_constructed.end())); - vec move_assigned = std::move(copy_assigned); + vec move_assigned = move(copy_assigned); assert(equal(move_assigned.begin(), move_assigned.end(), range_constructed.begin(), range_constructed.end())); assert(copy_assigned.empty()); #endif // __EDG__ @@ -355,23 +355,23 @@ _CONSTEXPR20_CONTAINER bool test_interface() { assert(e == false); const auto s = range_constructed.size(); - static_assert(is_same_v, std::size_t>); + static_assert(is_same_v, size_t>); assert(s == size(input)); const auto ms = range_constructed.max_size(); - static_assert(is_same_v, std::size_t>); - assert(ms == static_cast(std::numeric_limits::max())); + static_assert(is_same_v, size_t>); + assert(ms == static_cast(numeric_limits::max())); range_constructed.reserve(20); const auto c = range_constructed.capacity(); - static_assert(is_same_v, std::size_t>); + static_assert(is_same_v, size_t>); assert(c == 32); range_constructed.shrink_to_fit(); const auto c2 = range_constructed.capacity(); - static_assert(is_same_v, std::size_t>); + static_assert(is_same_v, size_t>); assert(c2 == 32); #endif // __EDG__ } @@ -606,8 +606,8 @@ _CONSTEXPR20_CONTAINER bool test_iterators() { const auto cit = range_constructed.cbegin() + 2; assert(cit[2] == false); - std::vector> vec2 = {{false, true}, {true, false}}; - const auto it2 = vec2.begin(); + vector> vec2 = {{false, true}, {true, false}}; + const auto it2 = vec2.begin(); assert(it2->second); const auto cit2 = vec2.cbegin(); From 664957b7825ab74b9535c83f6698799fd94525d5 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 11 Feb 2021 04:09:16 -0800 Subject: [PATCH 37/50] Test cleanup: Include headers. --- tests/std/tests/P0784R7_library_machinery/test.cpp | 3 +++ tests/std/tests/P1004R2_constexpr_vector/test.cpp | 3 +++ tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp | 4 ++++ 3 files changed, 10 insertions(+) diff --git a/tests/std/tests/P0784R7_library_machinery/test.cpp b/tests/std/tests/P0784R7_library_machinery/test.cpp index a5fa168550b..edc1f8a9609 100644 --- a/tests/std/tests/P0784R7_library_machinery/test.cpp +++ b/tests/std/tests/P0784R7_library_machinery/test.cpp @@ -3,7 +3,10 @@ #include #include +#include #include +#include +#include #pragma warning(disable : 4582) // '%s': constructor is not implicitly called #pragma warning(disable : 4583) // '%s': destructor is not implicitly called diff --git a/tests/std/tests/P1004R2_constexpr_vector/test.cpp b/tests/std/tests/P1004R2_constexpr_vector/test.cpp index 12362af2964..827e7f7a687 100644 --- a/tests/std/tests/P1004R2_constexpr_vector/test.cpp +++ b/tests/std/tests/P1004R2_constexpr_vector/test.cpp @@ -3,7 +3,10 @@ #include #include +#include +#include #include +#include #include #include diff --git a/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp b/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp index 15728c7d6b1..2c4b4c8eeca 100644 --- a/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp +++ b/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp @@ -3,7 +3,11 @@ #include #include +#include +#include +#include #include +#include #include #include From 0d7537b3b09e9424246d5a3867febe7242913506 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 11 Feb 2021 04:09:44 -0800 Subject: [PATCH 38/50] Test cleanup: Remove unnecessary semicolons. --- tests/std/tests/P0784R7_library_machinery/test.cpp | 4 ++-- tests/std/tests/P1004R2_constexpr_vector/test.cpp | 2 +- tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/std/tests/P0784R7_library_machinery/test.cpp b/tests/std/tests/P0784R7_library_machinery/test.cpp index edc1f8a9609..92da3881157 100644 --- a/tests/std/tests/P0784R7_library_machinery/test.cpp +++ b/tests/std/tests/P0784R7_library_machinery/test.cpp @@ -15,7 +15,7 @@ using namespace std; struct int_wrapper_copy { constexpr int_wrapper_copy() = default; - constexpr int_wrapper_copy(const int v) : _val(v){}; + constexpr int_wrapper_copy(const int v) : _val(v) {} constexpr int_wrapper_copy(const int_wrapper_copy& other) : _val(other._val) {} constexpr int_wrapper_copy& operator=(const int_wrapper_copy& other) { @@ -33,7 +33,7 @@ struct int_wrapper_copy { struct int_wrapper_move { constexpr int_wrapper_move() = default; - constexpr int_wrapper_move(const int v) : _val(v){}; + constexpr int_wrapper_move(const int v) : _val(v) {} constexpr int_wrapper_move(const int_wrapper_move&) = delete; constexpr int_wrapper_move& operator=(const int_wrapper_move&) = delete; diff --git a/tests/std/tests/P1004R2_constexpr_vector/test.cpp b/tests/std/tests/P1004R2_constexpr_vector/test.cpp index 827e7f7a687..b7dea59e973 100644 --- a/tests/std/tests/P1004R2_constexpr_vector/test.cpp +++ b/tests/std/tests/P1004R2_constexpr_vector/test.cpp @@ -29,7 +29,7 @@ struct soccc_allocator { _CONSTEXPR20_CONTAINER soccc_allocator(const soccc_allocator& other) noexcept : id(other.id), soccc_generation(other.soccc_generation) {} _CONSTEXPR20_CONTAINER soccc_allocator(const soccc_allocator& other) noexcept - : id(other.id + 1), soccc_generation(other.soccc_generation){}; + : id(other.id + 1), soccc_generation(other.soccc_generation) {} _CONSTEXPR20_CONTAINER soccc_allocator& operator=(const soccc_allocator&) noexcept { return *this; diff --git a/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp b/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp index 2c4b4c8eeca..903991708ea 100644 --- a/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp +++ b/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp @@ -31,7 +31,7 @@ struct soccc_allocator { _CONSTEXPR20_DYNALLOC soccc_allocator(const soccc_allocator& other) noexcept : id(other.id), soccc_generation(other.soccc_generation) {} _CONSTEXPR20_DYNALLOC soccc_allocator(const soccc_allocator& other) noexcept - : id(other.id + 1), soccc_generation(other.soccc_generation){}; + : id(other.id + 1), soccc_generation(other.soccc_generation) {} _CONSTEXPR20_DYNALLOC soccc_allocator& operator=(const soccc_allocator&) noexcept { return *this; From 8929334271252a9e19aef9b45d1857921f4a4320 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 11 Feb 2021 04:11:48 -0800 Subject: [PATCH 39/50] Test cleanup: Remove constexpr for deleted functions. --- tests/std/tests/P0784R7_library_machinery/test.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/std/tests/P0784R7_library_machinery/test.cpp b/tests/std/tests/P0784R7_library_machinery/test.cpp index 92da3881157..7009f2459c9 100644 --- a/tests/std/tests/P0784R7_library_machinery/test.cpp +++ b/tests/std/tests/P0784R7_library_machinery/test.cpp @@ -23,8 +23,8 @@ struct int_wrapper_copy { return *this; } - constexpr int_wrapper_copy(int_wrapper_copy&&) = delete; - constexpr int_wrapper_copy& operator=(int_wrapper_copy&&) = delete; + int_wrapper_copy(int_wrapper_copy&&) = delete; + int_wrapper_copy& operator=(int_wrapper_copy&&) = delete; constexpr bool operator==(const int_wrapper_copy&) const = default; @@ -35,8 +35,8 @@ struct int_wrapper_move { constexpr int_wrapper_move() = default; constexpr int_wrapper_move(const int v) : _val(v) {} - constexpr int_wrapper_move(const int_wrapper_move&) = delete; - constexpr int_wrapper_move& operator=(const int_wrapper_move&) = delete; + int_wrapper_move(const int_wrapper_move&) = delete; + int_wrapper_move& operator=(const int_wrapper_move&) = delete; constexpr int_wrapper_move(int_wrapper_move&& other) : _val(exchange(other._val, -1)) {} constexpr int_wrapper_move& operator=(int_wrapper_move&& other) { From a3f5a8d1cb56c80efa6ab1e708daabc84a83a3bb Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 11 Feb 2021 04:12:30 -0800 Subject: [PATCH 40/50] Test cleanup: This test is always C++20. --- tests/std/tests/P0784R7_library_machinery/test.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/tests/std/tests/P0784R7_library_machinery/test.cpp b/tests/std/tests/P0784R7_library_machinery/test.cpp index 7009f2459c9..80293a7a9ca 100644 --- a/tests/std/tests/P0784R7_library_machinery/test.cpp +++ b/tests/std/tests/P0784R7_library_machinery/test.cpp @@ -74,7 +74,7 @@ _CONSTEXPR20_DYNALLOC bool test() { assert(equal(begin(expected_copy), end(expected_copy), begin(output), end(output))); } -#if _HAS_CXX20 && defined(__cpp_constexpr_dynamic_alloc) +#if defined(__cpp_constexpr_dynamic_alloc) { // _Uninitialized_copy_unchecked int_wrapper_copy input[] = {1, 2, 3, 4}; int_wrapper_copy output[4]; @@ -84,7 +84,7 @@ _CONSTEXPR20_DYNALLOC bool test() { assert(result == end(output)); assert(equal(begin(expected_copy), end(expected_copy), begin(output), end(output))); } -#endif // _HAS_CXX20 && defined(__cpp_constexpr_dynamic_alloc) +#endif // defined(__cpp_constexpr_dynamic_alloc) { // _Move_unchecked int_wrapper_move input[] = {1, 2, 3, 4}; @@ -127,8 +127,7 @@ _CONSTEXPR20_DYNALLOC bool test() { } #endif // __cpp_lib_concepts -#if _HAS_CXX20 && defined(__cpp_constexpr_dynamic_alloc) \ - && (defined(__clang__) || defined(__EDG__)) // TRANSITION, DevCom-1333853 +#if defined(__cpp_constexpr_dynamic_alloc) && (defined(__clang__) || defined(__EDG__)) // TRANSITION, DevCom-1333853 { // _Uninitialized_move_unchecked int_wrapper_move input[] = {1, 2, 3, 4}; int_wrapper_move output[4]; @@ -141,7 +140,7 @@ _CONSTEXPR20_DYNALLOC bool test() { assert(equal(begin(input), end(input), begin(expected_after_move), end(expected_after_move))); } } -#endif // _HAS_CXX20 && defined(__cpp_constexpr_dynamic_alloc) && (defined(__clang__) || defined(__EDG__)) +#endif // defined(__cpp_constexpr_dynamic_alloc) && (defined(__clang__) || defined(__EDG__)) return true; } From a5e8e46d056e5be68404195f40c8667aa23b8759 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 11 Feb 2021 04:13:01 -0800 Subject: [PATCH 41/50] Test cleanup: Don't need to define op!= in C++20. --- tests/std/tests/P1004R2_constexpr_vector/test.cpp | 5 ----- tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp | 5 ----- 2 files changed, 10 deletions(-) diff --git a/tests/std/tests/P1004R2_constexpr_vector/test.cpp b/tests/std/tests/P1004R2_constexpr_vector/test.cpp index b7dea59e973..d43aaf3df3d 100644 --- a/tests/std/tests/P1004R2_constexpr_vector/test.cpp +++ b/tests/std/tests/P1004R2_constexpr_vector/test.cpp @@ -44,11 +44,6 @@ struct soccc_allocator { return id == other.id; } - template - _CONSTEXPR20_CONTAINER bool operator!=(const soccc_allocator& other) const noexcept { - return id != other.id; - } - _CONSTEXPR20_CONTAINER T* allocate(const size_t n) { return allocator{}.allocate(n); } diff --git a/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp b/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp index 903991708ea..4e7d5b8e0cf 100644 --- a/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp +++ b/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp @@ -46,11 +46,6 @@ struct soccc_allocator { return id == other.id; } - template - _CONSTEXPR20_DYNALLOC bool operator!=(const soccc_allocator& other) const noexcept { - return id != other.id; - } - _CONSTEXPR20_DYNALLOC T* allocate(const size_t n) { return allocator{}.allocate(n); } From 8df8d701eaa3629dbb675c56164960eef61fd710 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 11 Feb 2021 04:19:06 -0800 Subject: [PATCH 42/50] Test cleanup: Change 4 to sizeof(int). --- tests/std/tests/P1004R2_constexpr_vector/test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/std/tests/P1004R2_constexpr_vector/test.cpp b/tests/std/tests/P1004R2_constexpr_vector/test.cpp index d43aaf3df3d..3c3577f6b5a 100644 --- a/tests/std/tests/P1004R2_constexpr_vector/test.cpp +++ b/tests/std/tests/P1004R2_constexpr_vector/test.cpp @@ -347,7 +347,7 @@ _CONSTEXPR20_CONTAINER bool test_interface() { const auto ms = range_constructed.max_size(); static_assert(is_same_v, size_t>); - assert(ms == static_cast(-1) / 4); + assert(ms == static_cast(-1) / sizeof(int)); range_constructed.reserve(20); From 102aa91c9c00c2a9b3d58924bdbcbb43ad1678e6 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 11 Feb 2021 04:15:09 -0800 Subject: [PATCH 43/50] Test cleanup: Fix comment typos. --- tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp b/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp index 4e7d5b8e0cf..a697446697d 100644 --- a/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp +++ b/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp @@ -77,7 +77,7 @@ _CONSTEXPR20_CONTAINER bool test_interface() { #if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273296 assert(all_of( size_default_constructed.begin(), size_default_constructed.end(), [](const bool val) { return !val; })); -#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL ! =2 +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 #endif // __EDG__ #ifndef __EDG__ // TRANSITION, VSO-1274387 @@ -107,13 +107,13 @@ _CONSTEXPR20_CONTAINER bool test_interface() { #if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273296 assert(equal(copy_constructed.begin(), copy_constructed.end(), size_default_constructed.begin(), size_default_constructed.end())); -#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL ! =2 +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 vec move_constructed(move(copy_constructed)); #if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273296 assert(equal(move_constructed.begin(), move_constructed.end(), size_default_constructed.begin(), size_default_constructed.end())); -#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL ! =2 +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 assert(copy_constructed.empty()); #endif // __EDG__ From b967b7d81d105b8971a0344a4d2ffbc09dfecf6f Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 11 Feb 2021 04:15:31 -0800 Subject: [PATCH 44/50] Test addition: Verify default_constructed.empty(). --- tests/std/tests/P1004R2_constexpr_vector/test.cpp | 1 + tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/tests/std/tests/P1004R2_constexpr_vector/test.cpp b/tests/std/tests/P1004R2_constexpr_vector/test.cpp index 3c3577f6b5a..d0dd4346ad9 100644 --- a/tests/std/tests/P1004R2_constexpr_vector/test.cpp +++ b/tests/std/tests/P1004R2_constexpr_vector/test.cpp @@ -96,6 +96,7 @@ _CONSTEXPR20_CONTAINER bool test_interface() { // special member functions vec default_constructed; + assert(default_constructed.empty()); vec copy_constructed(size_default_constructed); #if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1274387 assert(equal(copy_constructed.begin(), copy_constructed.end(), size_default_constructed.begin(), diff --git a/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp b/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp index a697446697d..afdc9040de4 100644 --- a/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp +++ b/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp @@ -103,6 +103,7 @@ _CONSTEXPR20_CONTAINER bool test_interface() { // special member functions #ifndef __EDG__ // TRANSITION, VSO-1274387 vec default_constructed; + assert(default_constructed.empty()); vec copy_constructed(size_default_constructed); #if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273296 assert(equal(copy_constructed.begin(), copy_constructed.end(), size_default_constructed.begin(), From 6e3d24ea623dedb8e9fbf363126a403378fbf853 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 11 Feb 2021 03:04:35 -0800 Subject: [PATCH 45/50] Test cleanup: Comment moved-from assumptions. --- tests/std/tests/P1004R2_constexpr_vector/test.cpp | 8 ++++---- tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/std/tests/P1004R2_constexpr_vector/test.cpp b/tests/std/tests/P1004R2_constexpr_vector/test.cpp index d0dd4346ad9..8df48b1e69d 100644 --- a/tests/std/tests/P1004R2_constexpr_vector/test.cpp +++ b/tests/std/tests/P1004R2_constexpr_vector/test.cpp @@ -109,7 +109,7 @@ _CONSTEXPR20_CONTAINER bool test_interface() { size_default_constructed.end())); #endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 - assert(copy_constructed.empty()); + assert(copy_constructed.empty()); // implementation-specific assumption that moved-from is empty vec copy_assigned = range_constructed; #if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1274387 @@ -120,7 +120,7 @@ _CONSTEXPR20_CONTAINER bool test_interface() { #if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1274387 assert(equal(move_assigned.begin(), move_assigned.end(), range_constructed.begin(), range_constructed.end())); #endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 - assert(copy_assigned.empty()); + assert(copy_assigned.empty()); // implementation-specific assumption that moved-from is empty // allocator constructors soccc_allocator alloc(2, 3); @@ -143,7 +143,7 @@ _CONSTEXPR20_CONTAINER bool test_interface() { #if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273365 assert(all_of(al_move_constructed.begin(), al_move_constructed.end(), [](const int val) { return val == 7; })); #endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 - assert(al_copy_constructed.empty()); + assert(al_copy_constructed.empty()); // implementation-specific assumption that moved-from is empty assert(al_move_constructed.get_allocator().id == 4); assert(al_move_constructed.get_allocator().soccc_generation == 3); @@ -194,7 +194,7 @@ _CONSTEXPR20_CONTAINER bool test_interface() { move_constructed = move(copy_constructed); assert(equal( move_constructed.begin(), move_constructed.end(), range_constructed.begin(), range_constructed.end())); - assert(copy_constructed.empty()); + assert(copy_constructed.empty()); // implementation-specific assumption that moved-from is empty vec initializer_list_constructed; initializer_list_constructed = {0, 1, 2, 3, 4, 5}; diff --git a/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp b/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp index afdc9040de4..27e480d8dae 100644 --- a/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp +++ b/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp @@ -115,7 +115,7 @@ _CONSTEXPR20_CONTAINER bool test_interface() { assert(equal(move_constructed.begin(), move_constructed.end(), size_default_constructed.begin(), size_default_constructed.end())); #endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 - assert(copy_constructed.empty()); + assert(copy_constructed.empty()); // implementation-specific assumption that moved-from is empty #endif // __EDG__ #if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273365 @@ -125,7 +125,7 @@ _CONSTEXPR20_CONTAINER bool test_interface() { vec move_assigned = move(copy_assigned); assert(equal(move_assigned.begin(), move_assigned.end(), range_constructed.begin(), range_constructed.end())); - assert(copy_assigned.empty()); + assert(copy_assigned.empty()); // implementation-specific assumption that moved-from is empty #endif // __EDG__ #endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 @@ -151,7 +151,7 @@ _CONSTEXPR20_CONTAINER bool test_interface() { #if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273296 assert(all_of(al_move_constructed.begin(), al_move_constructed.end(), [](const bool val) { return val; })); #endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 - assert(al_copy_constructed.empty()); + assert(al_copy_constructed.empty()); // implementation-specific assumption that moved-from is empty assert(al_move_constructed.get_allocator().id == 4); assert(al_move_constructed.get_allocator().soccc_generation == 3); @@ -205,7 +205,7 @@ _CONSTEXPR20_CONTAINER bool test_interface() { move_constructed = move(copy_constructed); assert(equal( move_constructed.begin(), move_constructed.end(), range_constructed.begin(), range_constructed.end())); - assert(copy_constructed.empty()); + assert(copy_constructed.empty()); // implementation-specific assumption that moved-from is empty vec initializer_list_constructed; initializer_list_constructed = {true, false, true, true, false, true}; From 8d9dd5b5113edf0acde02bf4487c0e910952b158 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 11 Feb 2021 03:23:00 -0800 Subject: [PATCH 46/50] Test addition: Test the less-than etc. operators. --- .../std/tests/P1004R2_constexpr_vector/test.cpp | 16 ++++++++++++++++ .../tests/P1004R2_constexpr_vector_bool/test.cpp | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/tests/std/tests/P1004R2_constexpr_vector/test.cpp b/tests/std/tests/P1004R2_constexpr_vector/test.cpp index 8df48b1e69d..b5e0e6e31ea 100644 --- a/tests/std/tests/P1004R2_constexpr_vector/test.cpp +++ b/tests/std/tests/P1004R2_constexpr_vector/test.cpp @@ -491,6 +491,22 @@ _CONSTEXPR20_CONTAINER bool test_interface() { const auto ne = first != third; static_assert(is_same_v, bool>); assert(ne); + + const auto l = first < third; + static_assert(is_same_v, bool>); + assert(l); + + const auto le = first <= third; + static_assert(is_same_v, bool>); + assert(le); + + const auto g = first > third; + static_assert(is_same_v, bool>); + assert(!g); + + const auto ge = first >= third; + static_assert(is_same_v, bool>); + assert(!ge); } #endif // defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 || defined(MSVC_INTERNAL_TESTING) return true; diff --git a/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp b/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp index 27e480d8dae..7f09a0f5412 100644 --- a/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp +++ b/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp @@ -510,6 +510,22 @@ _CONSTEXPR20_CONTAINER bool test_interface() { const auto ne = first != third; static_assert(is_same_v, bool>); assert(ne); + + const auto l = first < third; + static_assert(is_same_v, bool>); + assert(!l); + + const auto le = first <= third; + static_assert(is_same_v, bool>); + assert(!le); + + const auto g = first > third; + static_assert(is_same_v, bool>); + assert(g); + + const auto ge = first >= third; + static_assert(is_same_v, bool>); + assert(ge); #endif // __EDG__ } #endif // defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 || defined(MSVC_INTERNAL_TESTING) From da106797addbab986d460dab7ee1d5b2933937e2 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 11 Feb 2021 03:45:05 -0800 Subject: [PATCH 47/50] Test cleanup: Remove iterator arrow test for vector. --- tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp b/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp index 7f09a0f5412..38cfb8883e6 100644 --- a/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp +++ b/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp @@ -621,13 +621,6 @@ _CONSTEXPR20_CONTAINER bool test_iterators() { const auto cit = range_constructed.cbegin() + 2; assert(cit[2] == false); - - vector> vec2 = {{false, true}, {true, false}}; - const auto it2 = vec2.begin(); - assert(it2->second); - - const auto cit2 = vec2.cbegin(); - assert(cit2->first == false); } #endif // __EDG__ #endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 From c06ac4c95191cb4e943b93465261540e13752d58 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 11 Feb 2021 03:53:24 -0800 Subject: [PATCH 48/50] Test change: Make soccc_allocator always equal, to meet the allocator requirements. --- tests/std/tests/P1004R2_constexpr_vector/test.cpp | 4 ++-- tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/std/tests/P1004R2_constexpr_vector/test.cpp b/tests/std/tests/P1004R2_constexpr_vector/test.cpp index b5e0e6e31ea..1d7358f0c94 100644 --- a/tests/std/tests/P1004R2_constexpr_vector/test.cpp +++ b/tests/std/tests/P1004R2_constexpr_vector/test.cpp @@ -40,8 +40,8 @@ struct soccc_allocator { } template - _CONSTEXPR20_CONTAINER bool operator==(const soccc_allocator& other) const noexcept { - return id == other.id; + _CONSTEXPR20_CONTAINER bool operator==(const soccc_allocator&) const noexcept { + return true; } _CONSTEXPR20_CONTAINER T* allocate(const size_t n) { diff --git a/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp b/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp index 38cfb8883e6..97b94d29f6c 100644 --- a/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp +++ b/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp @@ -42,8 +42,8 @@ struct soccc_allocator { } template - _CONSTEXPR20_DYNALLOC bool operator==(const soccc_allocator& other) const noexcept { - return id == other.id; + _CONSTEXPR20_DYNALLOC bool operator==(const soccc_allocator&) const noexcept { + return true; } _CONSTEXPR20_DYNALLOC T* allocate(const size_t n) { From 2a6e8c905723ac3c3578e6324d59f6687a0a4946 Mon Sep 17 00:00:00 2001 From: Miya Natsuhara Date: Tue, 16 Feb 2021 14:04:19 -0800 Subject: [PATCH 49/50] fix silly typo --- tests/libcxx/skipped_tests.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/libcxx/skipped_tests.txt b/tests/libcxx/skipped_tests.txt index 5fe19e8f505..e54f1dfb276 100644 --- a/tests/libcxx/skipped_tests.txt +++ b/tests/libcxx/skipped_tests.txt @@ -389,7 +389,7 @@ thread\macro.pass.cpp depr\depr.c.headers\tgmath_h.pass.cpp # LLVM-48606 "Clang rejects creation of struct with mutable member during constant evaluation" -language.support\support\limits\support.limits.general\vector.version.pass.cpp +language.support\support.limits\support.limits.general\vector.version.pass.cpp # *** CLANG ISSUES, NOT YET ANALYZED *** From 9946f9509ddcaa069823f4efe860c2464f466601 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 16 Feb 2021 17:39:48 -0800 Subject: [PATCH 50/50] Silence Clang warning. MSVC_INTERNAL_TESTING is non-ugly. --- .../std/tests/P1004R2_constexpr_vector_bool/test.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp b/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp index 97b94d29f6c..c1441f02775 100644 --- a/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp +++ b/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp @@ -15,8 +15,15 @@ using namespace std; #if defined(MSVC_INTERNAL_TESTING) || defined(__EDG__) \ || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1270433, VSO-1275530 +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-const-variable" // TRANSITION, LLVM-48606 +#endif // __clang__ static constexpr bool input[] = {true, false, true, true, false, true}; static constexpr bool input_flipped[] = {false, true, false, false, true, false}; +#ifdef __clang__ +#pragma clang diagnostic pop +#endif // __clang__ #endif // defined(MSVC_INTERNAL_TESTING) || defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 template @@ -67,7 +74,7 @@ using vec = vector>; _CONSTEXPR20_CONTAINER bool test_interface() { #if defined(__EDG__) \ - || _ITERATOR_DEBUG_LEVEL != 2 // || defined(_MSVC_INTERNAL_TESTING) // TRANSITION, VSO-1270433, VSO-1275530 + || _ITERATOR_DEBUG_LEVEL != 2 // || defined(MSVC_INTERNAL_TESTING) // TRANSITION, VSO-1270433, VSO-1275530 { // constructors // Non allocator constructors @@ -535,7 +542,7 @@ _CONSTEXPR20_CONTAINER bool test_interface() { _CONSTEXPR20_CONTAINER bool test_iterators() { #if defined(__EDG__) \ - || _ITERATOR_DEBUG_LEVEL != 2 // || defined(_MSVC_INTERNAL_TESTING) // TRANSITION, VSO-1270433, VSO-1275530 + || _ITERATOR_DEBUG_LEVEL != 2 // || defined(MSVC_INTERNAL_TESTING) // TRANSITION, VSO-1270433, VSO-1275530 #ifndef __EDG__ // TRANSITION, VSO-1274387 vec range_constructed(begin(input), end(input));