diff --git a/stl/inc/iterator b/stl/inc/iterator index 35c85717aad..6884d506bd5 100644 --- a/stl/inc/iterator +++ b/stl/inc/iterator @@ -585,10 +585,10 @@ public: // clang-format on switch (_That._Contains) { case _Variantish_state::_Holds_first: - _Construct_in_place(_First, _That._First); + _STD _Construct_in_place(_First, _That._Get_first()); break; case _Variantish_state::_Holds_second: - _Construct_in_place(_Second, _That._Second); + _STD _Construct_in_place(_Second, _That._Get_second()); break; case _Variantish_state::_Nothing: break; @@ -605,10 +605,10 @@ public: : _Contains{_That._Contains} { switch (_Contains) { case _Variantish_state::_Holds_first: - _Construct_in_place(_First, _That._First); + _STD _Construct_in_place(_First, _That._Get_first()); break; case _Variantish_state::_Holds_second: - _Construct_in_place(_Second, _That._Second); + _STD _Construct_in_place(_Second, _That._Get_second()); break; case _Variantish_state::_Nothing: break; @@ -625,10 +625,10 @@ public: : _Contains{_That._Contains} { switch (_Contains) { case _Variantish_state::_Holds_first: - _Construct_in_place(_First, _STD move(_That._First)); + _STD _Construct_in_place(_First, _STD move(_That._Get_first())); break; case _Variantish_state::_Holds_second: - _Construct_in_place(_Second, _STD move(_That._Second)); + _STD _Construct_in_place(_Second, _STD move(_That._Get_second())); break; case _Variantish_state::_Nothing: break; @@ -656,10 +656,10 @@ public: if (_Contains == _That._Contains) { switch (_Contains) { case _Variantish_state::_Holds_first: - _First = _That._First; + _Get_first() = _That._Get_first(); break; case _Variantish_state::_Holds_second: - _Second = _That._Second; + _Get_second() = _That._Get_second(); break; case _Variantish_state::_Nothing: break; @@ -672,10 +672,10 @@ public: switch (_That._Contains) { case _Variantish_state::_Holds_first: - _Construct_in_place(_First, _That._First); + _STD _Construct_in_place(_First, _That._Get_first()); break; case _Variantish_state::_Holds_second: - _Construct_in_place(_Second, _That._Second); + _STD _Construct_in_place(_Second, _That._Get_second()); break; case _Variantish_state::_Nothing: break; @@ -701,10 +701,10 @@ public: if (_Contains == _That._Contains) { switch (_Contains) { case _Variantish_state::_Holds_first: - _First = _STD move(_That._First); + _Get_first() = _STD move(_That._Get_first()); break; case _Variantish_state::_Holds_second: - _Second = _STD move(_That._Second); + _Get_second() = _STD move(_That._Get_second()); break; case _Variantish_state::_Nothing: break; @@ -717,10 +717,10 @@ public: switch (_That._Contains) { case _Variantish_state::_Holds_first: - _Construct_in_place(_First, _STD move(_That._First)); + _STD _Construct_in_place(_First, _STD move(_That._Get_first())); break; case _Variantish_state::_Holds_second: - _Construct_in_place(_Second, _STD move(_That._Second)); + _STD _Construct_in_place(_Second, _STD move(_That._Get_second())); break; case _Variantish_state::_Nothing: break; @@ -741,10 +741,10 @@ public: if (_Contains == _That._Contains) { switch (_Contains) { case _Variantish_state::_Holds_first: - _First = _That._First; + _Get_first() = _That._Get_first(); break; case _Variantish_state::_Holds_second: - _Second = _That._Second; + _Get_second() = _That._Get_second(); break; case _Variantish_state::_Nothing: break; @@ -757,10 +757,10 @@ public: switch (_That._Contains) { case _Variantish_state::_Holds_first: - _Construct_in_place(_First, _That._First); + _STD _Construct_in_place(_First, _That._Get_first()); break; case _Variantish_state::_Holds_second: - _Construct_in_place(_Second, _That._Second); + _STD _Construct_in_place(_Second, _That._Get_second()); break; case _Variantish_state::_Nothing: break; @@ -780,10 +780,10 @@ public: if (_Left._Contains == _Right._Contains) { switch (_Left._Contains) { case _Variantish_state::_Holds_first: - _RANGES swap(_Left._First, _Right._First); + _RANGES swap(_Left._Get_first(), _Right._Get_first()); break; case _Variantish_state::_Holds_second: - _RANGES swap(_Left._Second, _Right._Second); + _RANGES swap(_Left._Get_second(), _Right._Get_second()); break; case _Variantish_state::_Nothing: break; @@ -810,6 +810,20 @@ public: } } + _NODISCARD constexpr _Ty1& _Get_first() noexcept { + return _First; + } + _NODISCARD constexpr const _Ty1& _Get_first() const noexcept { + return _First; + } + + _NODISCARD constexpr _Ty2& _Get_second() noexcept { + return _Second; + } + _NODISCARD constexpr const _Ty2& _Get_second() const noexcept { + return _Second; + } + constexpr void _Clear() noexcept { _Raw_clear(); _Contains = _Variantish_state::_Nothing; @@ -819,7 +833,7 @@ public: constexpr void _Emplace_first(_Types&&... _Args) noexcept(is_nothrow_constructible_v<_Ty1, _Types...>) { _Clear(); - _Construct_in_place(_First, _STD forward<_Types>(_Args)...); + _STD _Construct_in_place(_First, _STD forward<_Types>(_Args)...); _Contains = _Variantish_state::_Holds_first; } @@ -827,13 +841,13 @@ public: constexpr void _Emplace_second(_Types&&... _Args) noexcept(is_nothrow_constructible_v<_Ty2, _Types...>) { _Clear(); - _Construct_in_place(_Second, _STD forward<_Types>(_Args)...); + _STD _Construct_in_place(_Second, _STD forward<_Types>(_Args)...); _Contains = _Variantish_state::_Holds_second; } union { - _Ty1 _First; - _Ty2 _Second; + remove_cv_t<_Ty1> _First; + remove_cv_t<_Ty2> _Second; }; _Variantish_state _Contains; @@ -896,7 +910,7 @@ public: _STL_VERIFY(_Val._Contains == _Variantish_state::_Holds_first, "common_iterator can only be dereferenced if it holds an iterator"); #endif // _ITERATOR_DEBUG_LEVEL != 0 - return *_Val._First; + return *_Val._Get_first(); } _NODISCARD constexpr decltype(auto) operator*() const @@ -906,7 +920,7 @@ public: _STL_VERIFY(_Val._Contains == _Variantish_state::_Holds_first, "common_iterator can only be dereferenced if it holds an iterator"); #endif // _ITERATOR_DEBUG_LEVEL != 0 - return *_Val._First; + return *_Val._Get_first(); } // clang-format off @@ -920,9 +934,9 @@ public: "common_iterator can only be dereferenced if it holds an iterator"); #endif // _ITERATOR_DEBUG_LEVEL != 0 if constexpr (_Has_member_arrow || is_pointer_v<_Iter>) { - return _Val._First; + return _Val._Get_first(); } else if constexpr (is_reference_v>) { - auto&& _Tmp = *_Val._First; + auto&& _Tmp = *_Val._Get_first(); return _STD addressof(_Tmp); } else { class _Arrow_proxy : private _Proxy_base { @@ -936,7 +950,7 @@ public: } }; - return _Arrow_proxy{*_Val._First}; + return _Arrow_proxy{*_Val._Get_first()}; } } @@ -945,7 +959,7 @@ public: _STL_VERIFY(_Val._Contains == _Variantish_state::_Holds_first, "common_iterator can only be incremented if it holds an iterator"); #endif // _ITERATOR_DEBUG_LEVEL != 0 - ++_Val._First; + ++_Val._Get_first(); return *this; } @@ -956,7 +970,7 @@ public: #endif // _ITERATOR_DEBUG_LEVEL != 0 if constexpr (forward_iterator<_Iter>) { common_iterator _Tmp = *this; - ++_Val._First; + ++_Val._Get_first(); return _Tmp; } else if constexpr (_Use_postfix_proxy<_Iter>) { class _Postfix_proxy : private _Proxy_base { @@ -970,11 +984,11 @@ public: } }; - _Postfix_proxy _Tmp{*_Val._First}; - ++_Val._First; + _Postfix_proxy _Tmp{*_Val._Get_first()}; + ++_Val._Get_first(); return _Tmp; } else { - return _Val._First++; + return _Val._Get_first()++; } } @@ -992,16 +1006,16 @@ public: if (_Left._Val._Contains == _Variantish_state::_Holds_first) { if (_Right_val._Contains == _Variantish_state::_Holds_first) { if constexpr (equality_comparable_with<_Iter, _OIter>) { - return _Left._Val._First == _Right_val._First; + return _Left._Val._Get_first() == _Right_val._Get_first(); } else { return true; } } else { - return _Left._Val._First == _Right_val._Second; + return _Left._Val._Get_first() == _Right_val._Get_second(); } } else { if (_Right_val._Contains == _Variantish_state::_Holds_first) { - return _Left._Val._Second == _Right_val._First; + return _Left._Val._Get_second() == _Right_val._Get_first(); } else { return true; } @@ -1021,13 +1035,13 @@ public: if (_Left._Val._Contains == _Variantish_state::_Holds_first) { if (_Right_val._Contains == _Variantish_state::_Holds_first) { - return _Left._Val._First - _Right_val._First; + return _Left._Val._Get_first() - _Right_val._Get_first(); } else { - return _Left._Val._First - _Right_val._Second; + return _Left._Val._Get_first() - _Right_val._Get_second(); } } else { if (_Right_val._Contains == _Variantish_state::_Holds_first) { - return _Left._Val._Second - _Right_val._First; + return _Left._Val._Get_second() - _Right_val._Get_first(); } else { return 0; } @@ -1035,26 +1049,26 @@ public: } _NODISCARD_FRIEND constexpr iter_rvalue_reference_t<_Iter> iter_move(const common_iterator& _Right) noexcept( - noexcept(_RANGES iter_move(_Right._Val._First))) + noexcept(_RANGES iter_move(_Right._Val._Get_first()))) requires input_iterator<_Iter> { #if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Right._Val._Contains == _Variantish_state::_Holds_first, "can only iter_move from common_iterator if it holds an iterator"); #endif // _ITERATOR_DEBUG_LEVEL != 0 - return _RANGES iter_move(_Right._Val._First); + return _RANGES iter_move(_Right._Val._Get_first()); } template _OIter, class _OSe> friend constexpr void iter_swap(const common_iterator& _Left, const common_iterator<_OIter, _OSe>& _Right) noexcept( - noexcept(_RANGES iter_swap(_Left._Val._First, _Right._Get_val()._First))) { + noexcept(_RANGES iter_swap(_Left._Val._Get_first(), _Right._Get_val()._Get_first()))) { auto& _Right_val = _Right._Get_val(); #if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Left._Val._Contains == _Variantish_state::_Holds_first && _Right_val._Contains == _Variantish_state::_Holds_first, "can only iter_swap common_iterators if both hold iterators"); #endif // _ITERATOR_DEBUG_LEVEL != 0 - return _RANGES iter_swap(_Left._Val._First, _Right_val._First); + return _RANGES iter_swap(_Left._Val._Get_first(), _Right_val._Get_first()); } _NODISCARD constexpr _Variantish<_Iter, _Se>& _Get_val() noexcept { diff --git a/stl/inc/memory b/stl/inc/memory index a0cdd884d7b..9ba2b098c14 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -530,15 +530,14 @@ namespace ranges { // clang-format off template - requires requires(void* _Void_ptr, _Types&&... _Args) { - ::new (_Void_ptr) _Ty(static_cast<_Types&&>(_Args)...); + requires requires(_Ty* _Ptr, _Types&&... _Args) { + ::new (static_cast(_Ptr)) _Ty(static_cast<_Types&&>(_Args)...); // per LWG-3888 } constexpr _Ty* operator()(_Ty* _Location, _Types&&... _Args) const - noexcept(noexcept(::new (const_cast(static_cast(_Location))) + noexcept(noexcept(::new (static_cast(_Location)) _Ty(_STD forward<_Types>(_Args)...))) /* strengthened */ { // clang-format on - _MSVC_CONSTEXPR return ::new (const_cast(static_cast(_Location))) - _Ty(_STD forward<_Types>(_Args)...); + _MSVC_CONSTEXPR return ::new (static_cast(_Location)) _Ty(_STD forward<_Types>(_Args)...); } }; @@ -935,6 +934,17 @@ namespace ranges { #endif // __cpp_lib_concepts #endif // _HAS_CXX17 +#if _HAS_CXX20 +template +_NODISCARD void* _Voidify_unfancy(_PtrTy _Ptr) noexcept { + if constexpr (is_pointer_v<_PtrTy>) { + return _Ptr; + } else { + return _STD addressof(*_Ptr); + } +} +#endif // _HAS_CXX20 + #if _HAS_DEPRECATED_RAW_STORAGE_ITERATOR _EXPORT_STD template class _CXX17_DEPRECATE_RAW_STORAGE_ITERATOR raw_storage_iterator { // wrap stores to raw buffer as output iterator @@ -956,12 +966,12 @@ public: } raw_storage_iterator& operator=(const _Ty& _Val) { // construct value designated by stored iterator - _Construct_in_place(*_Next, _Val); + _STD _Construct_in_place(const_cast<_Remove_cvref_t&>(*_Next), _Val); return *this; } raw_storage_iterator& operator=(_Ty&& _Val) { // construct value designated by stored iterator - _Construct_in_place(*_Next, _STD move(_Val)); + _STD _Construct_in_place(const_cast<_Remove_cvref_t&>(*_Next), _STD move(_Val)); return *this; } @@ -2081,12 +2091,12 @@ public: explicit _Ref_count_obj2(_Types&&... _Args) : _Ref_count_base() { #if _HAS_CXX20 if constexpr (sizeof...(_Types) == 1 && (is_same_v<_For_overwrite_tag, remove_cvref_t<_Types>> && ...)) { - _Default_construct_in_place(_Storage._Value); + _STD _Default_construct_in_place(_Storage._Value); ((void) _Args, ...); } else #endif // _HAS_CXX20 { - _Construct_in_place(_Storage._Value, _STD forward<_Types>(_Args)...); + _STD _Construct_in_place(_Storage._Value, _STD forward<_Types>(_Args)...); } } @@ -2099,7 +2109,7 @@ public: } union { - _Wrap<_Ty> _Storage; + _Wrap> _Storage; }; private: @@ -2201,12 +2211,12 @@ struct _NODISCARD _Uninitialized_rev_destroying_backout { template void _Emplace_back(_Types&&... _Vals) { // construct a new element at *_Last and increment - _Construct_in_place(*_Last, _STD forward<_Types>(_Vals)...); + _STD _Construct_in_place(*_Last, _STD forward<_Types>(_Vals)...); ++_Last; } void _Emplace_back_for_overwrite() { - _Default_construct_in_place(*_Last); + _STD _Default_construct_in_place(*_Last); ++_Last; } @@ -2350,7 +2360,7 @@ public: private: union { - _Wrap<_Element_type> _Storage; // flexible array must be last member + _Wrap> _Storage; // flexible array must be last member }; ~_Ref_count_unbounded_array() noexcept override { // TRANSITION, should be non-virtual @@ -2398,7 +2408,7 @@ private: size_t _Size; union { - _Wrap<_Element_type> _Storage; // flexible array must be last member + _Wrap> _Storage; // flexible array must be last member }; ~_Ref_count_unbounded_array() noexcept override { // TRANSITION, should be non-virtual @@ -2435,7 +2445,7 @@ public: } union { - _Wrap<_Ty> _Storage; + _Wrap> _Storage; }; private: @@ -2927,10 +2937,10 @@ _NODISCARD_SMART_PTR_ALLOC enable_if_t, shared_ptr<_Ty>> _Alblock _Rebound(_Al); _Alloc_construct_ptr _Constructor{_Rebound}; _Constructor._Allocate(); - ::new (_Voidify_iter(_Constructor._Ptr)) _Refc(_Al); + ::new (_STD _Voidify_unfancy(_Constructor._Ptr)) _Refc(_Al); shared_ptr<_Ty> _Ret; const auto _Ptr = static_cast*>(_Constructor._Ptr->_Storage._Value); - _Ret._Set_ptr_rep_and_enable_shared(_Ptr, _Unfancy(_Constructor._Release())); + _Ret._Set_ptr_rep_and_enable_shared(_Ptr, _STD _Unfancy(_Constructor._Release())); return _Ret; } @@ -2943,10 +2953,10 @@ _NODISCARD_SMART_PTR_ALLOC enable_if_t, shared_ptr<_Ty>> _Alblock _Rebound(_Al); _Alloc_construct_ptr _Constructor{_Rebound}; _Constructor._Allocate(); - ::new (_Voidify_iter(_Constructor._Ptr)) _Refc(_Al, _Val); + ::new (_STD _Voidify_unfancy(_Constructor._Ptr)) _Refc(_Al, _Val); shared_ptr<_Ty> _Ret; const auto _Ptr = static_cast*>(_Constructor._Ptr->_Storage._Value); - _Ret._Set_ptr_rep_and_enable_shared(_Ptr, _Unfancy(_Constructor._Release())); + _Ret._Set_ptr_rep_and_enable_shared(_Ptr, _STD _Unfancy(_Constructor._Release())); return _Ret; } @@ -2961,9 +2971,9 @@ _NODISCARD_SMART_PTR_ALLOC enable_if_t, shared_ptr<_T _Alblock _Rebound(_Al); _Alloc_construct_ptr _Constructor{_Rebound}; _Constructor._Allocate(); - ::new (_Voidify_iter(_Constructor._Ptr)) _Refc(_Al, _For_overwrite_tag{}); + ::new (_STD _Voidify_unfancy(_Constructor._Ptr)) _Refc(_Al, _For_overwrite_tag{}); const auto _Ptr = static_cast*>(_Constructor._Ptr->_Storage._Value); - _Ret._Set_ptr_rep_and_enable_shared(_Ptr, _Unfancy(_Constructor._Release())); + _Ret._Set_ptr_rep_and_enable_shared(_Ptr, _STD _Unfancy(_Constructor._Release())); } else { // make a shared_ptr to non-array object using _Refoa = _Ref_count_obj_alloc3, _Alloc>; @@ -2971,9 +2981,9 @@ _NODISCARD_SMART_PTR_ALLOC enable_if_t, shared_ptr<_T _Alblock _Rebound(_Al); _Alloc_construct_ptr<_Alblock> _Constructor{_Rebound}; _Constructor._Allocate(); - _Construct_in_place(*_Constructor._Ptr, _Al, _For_overwrite_tag{}); + _STD _Construct_in_place(*_Constructor._Ptr, _Al, _For_overwrite_tag{}); const auto _Ptr = reinterpret_cast<_Ty*>(_STD addressof(_Constructor._Ptr->_Storage._Value)); - _Ret._Set_ptr_rep_and_enable_shared(_Ptr, _Unfancy(_Constructor._Release())); + _Ret._Set_ptr_rep_and_enable_shared(_Ptr, _STD _Unfancy(_Constructor._Release())); } return _Ret; diff --git a/stl/inc/optional b/stl/inc/optional index a86eaa23be7..e67dac9eba5 100644 --- a/stl/inc/optional +++ b/stl/inc/optional @@ -71,7 +71,7 @@ template > struct _Optional_destruct_base { // either contains a value of _Ty or is empty (trivial destructor) union { _Nontrivial_dummy_type _Dummy; - remove_const_t<_Ty> _Value; + remove_cv_t<_Ty> _Value; }; bool _Has_value; @@ -98,7 +98,7 @@ template struct _Optional_destruct_base<_Ty, false> { // either contains a value of _Ty or is empty (non-trivial destructor) union { _Nontrivial_dummy_type _Dummy; - remove_const_t<_Ty> _Value; + remove_cv_t<_Ty> _Value; }; bool _Has_value; @@ -154,7 +154,7 @@ struct _Optional_construct_base : _Optional_destruct_base<_Ty> { is_nothrow_assignable_v<_Ty&, _Ty2>&& is_nothrow_constructible_v<_Ty, _Ty2>) { // assign / initialize the contained value from _Right if (this->_Has_value) { - this->_Value = _STD forward<_Ty2>(_Right); + static_cast<_Ty&>(this->_Value) = _STD forward<_Ty2>(_Right); } else { _Construct(_STD forward<_Ty2>(_Right)); } @@ -425,7 +425,7 @@ public: "optional::value_or(U) requires U to be convertible to T (N4828 [optional.observe]/18)."); if (this->_Has_value) { - return this->_Value; + return static_cast(this->_Value); } return static_cast>(_STD forward<_Ty2>(_Right)); @@ -439,7 +439,7 @@ public: "optional::value_or(U) requires U to be convertible to T (N4828 [optional.observe]/20)."); if (this->_Has_value) { - return _STD move(this->_Value); + return static_cast<_Ty&&>(this->_Value); } return static_cast>(_STD forward<_Ty2>(_Right)); @@ -455,7 +455,7 @@ public: "(N4901 [optional.monadic]/2)."); if (this->_Has_value) { - return _STD invoke(_STD forward<_Fn>(_Func), this->_Value); + return _STD invoke(_STD forward<_Fn>(_Func), static_cast<_Ty&>(this->_Value)); } else { return remove_cvref_t<_Uty>{}; } @@ -470,7 +470,7 @@ public: "(N4901 [optional.monadic]/2)."); if (this->_Has_value) { - return _STD invoke(_STD forward<_Fn>(_Func), this->_Value); + return _STD invoke(_STD forward<_Fn>(_Func), static_cast(this->_Value)); } else { return remove_cvref_t<_Uty>{}; } @@ -485,7 +485,7 @@ public: "(N4901 [optional.monadic]/5)."); if (this->_Has_value) { - return _STD invoke(_STD forward<_Fn>(_Func), _STD move(this->_Value)); + return _STD invoke(_STD forward<_Fn>(_Func), static_cast<_Ty&&>(this->_Value)); } else { return remove_cvref_t<_Uty>{}; } @@ -500,7 +500,7 @@ public: "(N4901 [optional.monadic]/5)."); if (this->_Has_value) { - return _STD invoke(_STD forward<_Fn>(_Func), _STD move(this->_Value)); + return _STD invoke(_STD forward<_Fn>(_Func), static_cast(this->_Value)); } else { return remove_cvref_t<_Uty>{}; } @@ -518,7 +518,8 @@ public: "(N4901 [optional.monadic]/8)."); if (this->_Has_value) { - return optional<_Uty>{_Construct_from_invoke_result_tag{}, _STD forward<_Fn>(_Func), this->_Value}; + return optional<_Uty>{ + _Construct_from_invoke_result_tag{}, _STD forward<_Fn>(_Func), static_cast<_Ty&>(this->_Value)}; } else { return optional<_Uty>{}; } @@ -536,7 +537,8 @@ public: "(N4901 [optional.monadic]/8)."); if (this->_Has_value) { - return optional<_Uty>{_Construct_from_invoke_result_tag{}, _STD forward<_Fn>(_Func), this->_Value}; + return optional<_Uty>{ + _Construct_from_invoke_result_tag{}, _STD forward<_Fn>(_Func), static_cast(this->_Value)}; } else { return optional<_Uty>{}; } @@ -555,7 +557,7 @@ public: if (this->_Has_value) { return optional<_Uty>{ - _Construct_from_invoke_result_tag{}, _STD forward<_Fn>(_Func), _STD move(this->_Value)}; + _Construct_from_invoke_result_tag{}, _STD forward<_Fn>(_Func), static_cast<_Ty&&>(this->_Value)}; } else { return optional<_Uty>{}; } @@ -574,7 +576,7 @@ public: if (this->_Has_value) { return optional<_Uty>{ - _Construct_from_invoke_result_tag{}, _STD forward<_Fn>(_Func), _STD move(this->_Value)}; + _Construct_from_invoke_result_tag{}, _STD forward<_Fn>(_Func), static_cast(this->_Value)}; } else { return optional<_Uty>{}; } diff --git a/stl/inc/ranges b/stl/inc/ranges index ab03fe9702f..12248bb7243 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -290,7 +290,7 @@ namespace ranges { requires copy_constructible<_Ty> : _Engaged{_That._Engaged} { if (_That._Engaged) { - _Construct_in_place(_Val, _That._Val); + _STD _Construct_in_place(_Val, static_cast(_That._Val)); } } @@ -300,7 +300,7 @@ namespace ranges { constexpr _Movable_box(_Movable_box&& _That) : _Engaged{_That._Engaged} { if (_That._Engaged) { - _Construct_in_place(_Val, _STD move(_That._Val)); + _STD _Construct_in_place(_Val, static_cast<_Ty&&>(_That._Val)); } } @@ -315,14 +315,14 @@ namespace ranges { { if (_Engaged) { if (_That._Engaged) { - _Val = _That._Val; + static_cast<_Ty&>(_Val) = static_cast(_That._Val); } else { _Val.~_Ty(); _Engaged = false; } } else { if (_That._Engaged) { - _Construct_in_place(_Val, _That._Val); + _STD _Construct_in_place(_Val, static_cast(_That._Val)); _Engaged = true; } else { // nothing to do @@ -345,7 +345,7 @@ namespace ranges { } if (_That._Engaged) { - _Construct_in_place(_Val, _That._Val); + _STD _Construct_in_place(_Val, static_cast(_That._Val)); _Engaged = true; } @@ -363,14 +363,14 @@ namespace ranges { { if (_Engaged) { if (_That._Engaged) { - _Val = _STD move(_That._Val); + static_cast<_Ty&>(_Val) = static_cast<_Ty&&>(_That._Val); } else { _Val.~_Ty(); _Engaged = false; } } else { if (_That._Engaged) { - _Construct_in_place(_Val, _STD move(_That._Val)); + _STD _Construct_in_place(_Val, static_cast<_Ty&&>(_That._Val)); _Engaged = true; } else { // nothing to do @@ -391,7 +391,7 @@ namespace ranges { } if (_That._Engaged) { - _Construct_in_place(_Val, _STD move(_That._Val)); + _STD _Construct_in_place(_Val, static_cast<_Ty&&>(_That._Val)); _Engaged = true; } @@ -413,7 +413,7 @@ namespace ranges { private: union { - _Ty _Val; + remove_cv_t<_Ty> _Val; }; bool _Engaged; }; @@ -429,6 +429,9 @@ namespace ranges { // is_nothrow_move_constructible_v is true. : movable<_Ty> || is_nothrow_move_constructible_v<_Ty>); + template + concept _Copy_constructible_for_box = is_copy_constructible_v<_Ty>; + template <_Valid_movable_box_object _Ty> requires _Use_simple_movable_box_wrapper<_Ty> class _Movable_box<_Ty> { // provide the same API more efficiently when we can avoid the disengaged state @@ -442,31 +445,50 @@ namespace ranges { is_nothrow_constructible_v<_Ty, _Types...>) // strengthened : _Val(_STD forward<_Types>(_Args)...) {} - _Movable_box(const _Movable_box&) = default; - _Movable_box(_Movable_box&&) = default; + // clang-format off + _Movable_box(const _Movable_box&) + requires _Copy_constructible_for_box<_Ty> && is_trivially_copy_constructible_v<_Ty> = default; + _Movable_box(_Movable_box&&) requires is_trivially_move_constructible_v<_Ty> = default; + // clang-format on + + constexpr _Movable_box(const _Movable_box& _That) noexcept(is_nothrow_copy_constructible_v<_Ty>) + requires _Copy_constructible_for_box<_Ty> + : _Val(static_cast(_That._Val)) {} + + constexpr _Movable_box(_Movable_box&& _That) noexcept(is_nothrow_move_constructible_v<_Ty>) + : _Val(static_cast<_Ty&&>(_That._Val)) {} // clang-format off - _Movable_box& operator=(const _Movable_box&) requires copyable<_Ty> = default; - _Movable_box& operator=(_Movable_box&&) requires movable<_Ty> = default; + _Movable_box& operator=(const _Movable_box&) + requires copyable<_Ty> && is_trivially_copy_assignable_v<_Ty> = default; + _Movable_box& operator=(_Movable_box&&) requires movable<_Ty> && is_trivially_move_assignable_v<_Ty> = default; // clang-format on - constexpr _Movable_box& operator=(const _Movable_box& _That) noexcept + constexpr _Movable_box& operator=(const _Movable_box& _That) noexcept( + is_nothrow_copy_assignable_v<_Ty> || !copyable<_Ty>) // strengthened requires copy_constructible<_Ty> { - if (_STD addressof(_That) != this) { - _Val.~_Ty(); - _Construct_in_place(_Val, _That._Val); + if constexpr (copyable<_Ty>) { + static_cast<_Ty&>(_Val) = static_cast(_That._Val); + } else { + if (_STD addressof(_That) != this) { + _Val.~_Ty(); + _STD _Construct_in_place(_Val, static_cast(_That._Val)); + } } - return *this; } - constexpr _Movable_box& operator=(_Movable_box&& _That) noexcept { - if (_STD addressof(_That) != this) { - _Val.~_Ty(); - _Construct_in_place(_Val, _STD move(_That._Val)); + constexpr _Movable_box& operator=(_Movable_box&& _That) noexcept( + is_nothrow_move_assignable_v<_Ty> || !movable<_Ty>) /* strengthened */ { + if constexpr (movable<_Ty>) { + static_cast<_Ty&>(_Val) = static_cast<_Ty&&>(_That._Val); + } else { + if (_STD addressof(_That) != this) { + _Val.~_Ty(); + _STD _Construct_in_place(_Val, static_cast<_Ty&&>(_That._Val)); + } } - return *this; } @@ -482,7 +504,7 @@ namespace ranges { } private: - /* [[no_unique_address]] */ _Ty _Val{}; + /* [[no_unique_address]] */ remove_cv_t<_Ty> _Val{}; }; template @@ -507,7 +529,7 @@ namespace ranges { requires copy_constructible<_Ty> : _Engaged{_That._Engaged} { if (_That._Engaged) { - _Construct_in_place(_Val, _That._Val); + _STD _Construct_in_place(_Val, static_cast(_That._Val)); } } @@ -517,7 +539,7 @@ namespace ranges { constexpr _Defaultabox(_Defaultabox&& _That) : _Engaged{_That._Engaged} { if (_That._Engaged) { - _Construct_in_place(_Val, _STD move(_That._Val)); + _STD _Construct_in_place(_Val, static_cast<_Ty&&>(_That._Val)); } } @@ -525,7 +547,7 @@ namespace ranges { requires convertible_to constexpr _Defaultabox(const _Defaultabox<_Uty>& _That) : _Engaged{_That} { if (_That) { - _Construct_in_place(_Val, *_That); + _STD _Construct_in_place(_Val, *_That); } } @@ -533,7 +555,7 @@ namespace ranges { requires convertible_to<_Uty, _Ty> constexpr _Defaultabox(_Defaultabox<_Uty>&& _That) : _Engaged{_That} { if (_That) { - _Construct_in_place(_Val, _STD move(*_That)); + _STD _Construct_in_place(_Val, _STD move(*_That)); } } @@ -548,14 +570,14 @@ namespace ranges { { if (_Engaged) { if (_That._Engaged) { - _Val = _That._Val; + static_cast<_Ty&>(_Val) = static_cast(_That._Val); } else { _Val.~_Ty(); _Engaged = false; } } else { if (_That._Engaged) { - _Construct_in_place(_Val, _That._Val); + _STD _Construct_in_place(_Val, static_cast(_That._Val)); _Engaged = true; } else { // nothing to do @@ -573,14 +595,14 @@ namespace ranges { is_nothrow_move_constructible_v<_Ty>&& is_nothrow_move_assignable_v<_Ty>) /* strengthened */ { if (_Engaged) { if (_That._Engaged) { - _Val = _STD move(_That._Val); + static_cast<_Ty&>(_Val) = static_cast<_Ty&&>(_That._Val); } else { _Val.~_Ty(); _Engaged = false; } } else { if (_That._Engaged) { - _Construct_in_place(_Val, _STD move(_That._Val)); + _STD _Construct_in_place(_Val, static_cast<_Ty&&>(_That._Val)); _Engaged = true; } else { // nothing to do @@ -593,9 +615,9 @@ namespace ranges { constexpr _Defaultabox& operator=(_Ty&& _That) noexcept( is_nothrow_move_constructible_v<_Ty>&& is_nothrow_move_assignable_v<_Ty>) { if (_Engaged) { - _Val = _STD move(_That); + static_cast<_Ty&>(_Val) = _STD move(_That); } else { - _Construct_in_place(_Val, _STD move(_That)); + _STD _Construct_in_place(_Val, _STD move(_That)); _Engaged = true; } @@ -607,9 +629,9 @@ namespace ranges { requires copyable<_Ty> { if (_Engaged) { - _Val = _That; + static_cast<_Ty&>(_Val) = _That; } else { - _Construct_in_place(_Val, _That); + _STD _Construct_in_place(_Val, _That); _Engaged = true; } @@ -636,14 +658,16 @@ namespace ranges { } } - _NODISCARD constexpr bool operator==(const _Defaultabox& _That) const noexcept(noexcept(_Val == _That._Val)) { + _NODISCARD constexpr bool operator==(const _Defaultabox& _That) const + noexcept(noexcept(static_cast(_Val) == static_cast(_That._Val))) { _STL_INTERNAL_STATIC_ASSERT(equality_comparable<_Ty>); - return _Engaged == _That._Engaged && (!_Engaged || _Val == _That._Val); + return _Engaged == _That._Engaged + && (!_Engaged || static_cast(_Val) == static_cast(_That._Val)); } private: union { - _Ty _Val; + remove_cv_t<_Ty> _Val; }; bool _Engaged = false; }; @@ -775,7 +799,7 @@ namespace ranges { _Engaged = false; } - _Construct_in_place(_Val, _STD forward<_Types>(_Args)...); + _STD _Construct_in_place(_Val, _STD forward<_Types>(_Args)...); _Engaged = true; return _Val; @@ -783,7 +807,7 @@ namespace ranges { private: union { - _Ty _Val; + remove_cv_t<_Ty> _Val; }; bool _Engaged = false; }; @@ -818,13 +842,13 @@ namespace ranges { template constexpr _Ty& _Emplace(_Types&&... _Args) noexcept(is_nothrow_constructible_v<_Ty, _Types...>) { - _Construct_in_place(_Val, _STD forward<_Types>(_Args)...); + _STD _Construct_in_place(_Val, _STD forward<_Types>(_Args)...); return _Val; } private: union { - _Ty _Val; + remove_cv_t<_Ty> _Val; }; }; @@ -4136,18 +4160,18 @@ namespace ranges { template constexpr _Ret _Visit_inner_it(auto&& _Func) const { if (_Inner_it._Contains == _Variantish_state::_Holds_first) { - return _Func(_Inner_it._First); + return _Func(_Inner_it._Get_first()); } else if (_Inner_it._Contains == _Variantish_state::_Holds_second) { - return _Func(_Inner_it._Second); + return _Func(_Inner_it._Get_second()); } else { - _Throw_bad_variant_access(); + _STD _Throw_bad_variant_access(); } } constexpr void _Satisfy() { for (;;) { if (_Inner_it._Contains == _Variantish_state::_Holds_first) { - if (_Inner_it._First != _RANGES end(_Parent->_Pattern)) { + if (_Inner_it._Get_first() != _RANGES end(_Parent->_Pattern)) { break; } @@ -4155,7 +4179,7 @@ namespace ranges { } else { _STL_INTERNAL_CHECK(_Inner_it._Contains == _Variantish_state::_Holds_second); - if (_Inner_it._Second != _RANGES end(_Get_inner())) { + if (_Inner_it._Get_second() != _RANGES end(_Get_inner())) { break; } @@ -4195,13 +4219,13 @@ namespace ranges { : _Mybase(_STD move(_It._Outer_it)), _Parent(_It._Parent) { switch (_It._Inner_it._Contains) { case _Variantish_state::_Holds_first: - _Inner_it._Emplace_first(_STD move(_It._Inner_it._First)); + _Inner_it._Emplace_first(_STD move(_It._Inner_it._Get_first())); break; case _Variantish_state::_Holds_second: - _Inner_it._Emplace_second(_STD move(_It._Inner_it._Second)); + _Inner_it._Emplace_second(_STD move(_It._Inner_it._Get_second())); break; case _Variantish_state::_Nothing: - _Throw_bad_variant_access(); + _STD _Throw_bad_variant_access(); } } @@ -4213,13 +4237,13 @@ namespace ranges { constexpr _Iterator& operator++() { switch (_Inner_it._Contains) { case _Variantish_state::_Holds_first: - ++_Inner_it._First; + ++_Inner_it._Get_first(); break; case _Variantish_state::_Holds_second: - ++_Inner_it._Second; + ++_Inner_it._Get_second(); break; case _Variantish_state::_Nothing: - _Throw_bad_variant_access(); + _STD _Throw_bad_variant_access(); } _Satisfy(); return *this; @@ -4249,7 +4273,7 @@ namespace ranges { for (;;) { if (_Inner_it._Contains == _Variantish_state::_Holds_first) { - auto& _It = _Inner_it._First; + auto& _It = _Inner_it._Get_first(); if (_It == _RANGES begin(_Parent->_Pattern)) { --_Outer_it; _Inner_it._Emplace_second(_RANGES end(_Get_inner())); @@ -4257,26 +4281,26 @@ namespace ranges { break; } } else if (_Inner_it._Contains == _Variantish_state::_Holds_second) { - auto& _It = _Inner_it._Second; + auto& _It = _Inner_it._Get_second(); if (_It == _RANGES begin(_Get_inner())) { _Inner_it._Emplace_first(_RANGES end(_Parent->_Pattern)); } else { break; } } else { - _Throw_bad_variant_access(); + _STD _Throw_bad_variant_access(); } } switch (_Inner_it._Contains) { case _Variantish_state::_Holds_first: - --_Inner_it._First; + --_Inner_it._Get_first(); break; case _Variantish_state::_Holds_second: - --_Inner_it._Second; + --_Inner_it._Get_second(); break; case _Variantish_state::_Nothing: - _Throw_bad_variant_access(); + _STD _Throw_bad_variant_access(); } return *this; } @@ -4303,9 +4327,9 @@ namespace ranges { switch (_Left._Inner_it._Contains) { case _Variantish_state::_Holds_first: - return _Left._Inner_it._First == _Right._Inner_it._First; + return _Left._Inner_it._Get_first() == _Right._Inner_it._Get_first(); case _Variantish_state::_Holds_second: - return _Left._Inner_it._Second == _Right._Inner_it._Second; + return _Left._Inner_it._Get_second() == _Right._Inner_it._Get_second(); case _Variantish_state::_Nothing: return true; } @@ -4326,9 +4350,9 @@ namespace ranges { case _Variantish_state::_Holds_first: switch (_Right._Inner_it._Contains) { case _Variantish_state::_Holds_first: - return _RANGES iter_swap(_Left._Inner_it._First, _Right._Inner_it._First); + return _RANGES iter_swap(_Left._Inner_it._Get_first(), _Right._Inner_it._Get_first()); case _Variantish_state::_Holds_second: - return _RANGES iter_swap(_Left._Inner_it._First, _Right._Inner_it._Second); + return _RANGES iter_swap(_Left._Inner_it._Get_first(), _Right._Inner_it._Get_second()); case _Variantish_state::_Nothing: break; } @@ -4336,9 +4360,9 @@ namespace ranges { case _Variantish_state::_Holds_second: switch (_Right._Inner_it._Contains) { case _Variantish_state::_Holds_first: - return _RANGES iter_swap(_Left._Inner_it._Second, _Right._Inner_it._First); + return _RANGES iter_swap(_Left._Inner_it._Get_second(), _Right._Inner_it._Get_first()); case _Variantish_state::_Holds_second: - return _RANGES iter_swap(_Left._Inner_it._Second, _Right._Inner_it._Second); + return _RANGES iter_swap(_Left._Inner_it._Get_second(), _Right._Inner_it._Get_second()); case _Variantish_state::_Nothing: break; } @@ -4347,7 +4371,7 @@ namespace ranges { break; } - _Throw_bad_variant_access(); + _STD _Throw_bad_variant_access(); } }; diff --git a/stl/inc/variant b/stl/inc/variant index c0008799ea1..670c5b4af3e 100644 --- a/stl/inc/variant +++ b/stl/inc/variant @@ -377,7 +377,7 @@ class _Variant_storage_ { // Storage for variant alterna public: static constexpr size_t _Size = 1 + sizeof...(_Rest); union { - remove_const_t<_First> _Head; + remove_cv_t<_First> _Head; _Variant_storage<_Rest...> _Tail; }; @@ -412,7 +412,7 @@ class _Variant_storage_ { // Storage for variant altern public: static constexpr size_t _Size = 1 + sizeof...(_Rest); union { - remove_const_t<_First> _Head; + remove_cv_t<_First> _Head; _Variant_storage<_Rest...> _Tail; }; @@ -457,7 +457,7 @@ public: // wrapper to enable minimal hats-in-variants support. template struct _Variant_item { - remove_const_t<_Ty> _Item; + remove_cv_t<_Ty> _Item; template constexpr _Variant_item(_Types&&... _Args) noexcept(is_nothrow_constructible_v<_Ty, _Types...>) diff --git a/stl/inc/xmemory b/stl/inc/xmemory index e1dd28ef45c..6f2a28fb780 100644 --- a/stl/inc/xmemory +++ b/stl/inc/xmemory @@ -704,13 +704,10 @@ struct _Default_allocator_traits { // traits for std::allocator template static _CONSTEXPR20 void construct(_Alloc&, _Objty* const _Ptr, _Types&&... _Args) { #if _HAS_CXX20 - if (_STD is_constant_evaluated()) { - _STD construct_at(_Ptr, _STD forward<_Types>(_Args)...); - } else -#endif // _HAS_CXX20 - { - ::new (_Voidify_iter(_Ptr)) _Objty(_STD forward<_Types>(_Args)...); - } + _STD construct_at(_Ptr, _STD forward<_Types>(_Args)...); +#else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv + ::new (const_cast(static_cast(_Ptr))) _Objty(_STD forward<_Types>(_Args)...); +#endif // ^^^ !_HAS_CXX20 ^^^ } template @@ -978,7 +975,7 @@ public: template _CXX17_DEPRECATE_OLD_ALLOCATOR_MEMBERS void construct(_Objty* const _Ptr, _Types&&... _Args) { - ::new (_Voidify_iter(_Ptr)) _Objty(_STD forward<_Types>(_Args)...); + ::new (const_cast(static_cast(_Ptr))) _Objty(_STD forward<_Types>(_Args)...); } template @@ -1634,9 +1631,11 @@ _CONSTEXPR20 _NoThrowFwdIt _Uninitialized_move_unchecked(_InIt _First, const _In #ifdef __cpp_lib_concepts namespace ranges { template - concept _No_throw_input_iterator = input_iterator<_It> // - && is_lvalue_reference_v> // - && same_as>, iter_value_t<_It>>; + concept _No_throw_input_iterator = + input_iterator<_It> // + && is_lvalue_reference_v> // + && same_as>, remove_reference_t>> // per LWG-3888 + && same_as>, iter_value_t<_It>>; template concept _No_throw_sentinel_for = sentinel_for<_Se, _It>; diff --git a/stl/inc/xpolymorphic_allocator.h b/stl/inc/xpolymorphic_allocator.h index 5957f4333d0..44ae61c4bd6 100644 --- a/stl/inc/xpolymorphic_allocator.h +++ b/stl/inc/xpolymorphic_allocator.h @@ -279,7 +279,13 @@ namespace pmr { void construct(_Uty* const _Ptr, _Types&&... _Args) { // propagate allocator *this if uses_allocator_v, polymorphic_allocator> #if _HAS_CXX20 - _STD uninitialized_construct_using_allocator(_Ptr, *this, _STD forward<_Types>(_Args)...); + // equivalent to calling uninitialized_construct_using_allocator except for handling of cv-qualification + _STD apply( + [_Ptr](auto&&... _Construct_args) { + return ::new (const_cast(static_cast(_Ptr))) + _Uty(_STD forward(_Construct_args)...); + }, + _STD uses_allocator_construction_args<_Uty>(*this, _STD forward<_Types>(_Args)...)); #else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv allocator _Al{}; if constexpr (_Is_cv_pair<_Uty>) { diff --git a/stl/inc/xsmf_control.h b/stl/inc/xsmf_control.h index a288c7e3047..54ad04b67c7 100644 --- a/stl/inc/xsmf_control.h +++ b/stl/inc/xsmf_control.h @@ -34,10 +34,20 @@ struct _Non_trivial_copy : _Base { // non-trivial copy construction facade _Non_trivial_copy& operator=(_Non_trivial_copy&&) = default; }; +template +struct _Deleted_copy : _Base { // deleted copy construction facade + using _Base::_Base; + + _Deleted_copy() = default; + _Deleted_copy(const _Deleted_copy&) = delete; + _Deleted_copy(_Deleted_copy&&) = default; + _Deleted_copy& operator=(const _Deleted_copy&) = default; + _Deleted_copy& operator=(_Deleted_copy&&) = default; +}; + template -using _SMF_control_copy = conditional_t< - conjunction_v..., negation...>>>, - _Non_trivial_copy<_Base>, _Base>; +using _SMF_control_copy = conditional_t...>, _Base, + conditional_t...>, _Non_trivial_copy<_Base>, _Deleted_copy<_Base>>>; template struct _Non_trivial_move : _SMF_control_copy<_Base, _Types...> { // non-trivial move construction facade @@ -55,9 +65,22 @@ struct _Non_trivial_move : _SMF_control_copy<_Base, _Types...> { // non-trivial }; template -using _SMF_control_move = conditional_t< - conjunction_v..., negation...>>>, - _Non_trivial_move<_Base, _Types...>, _SMF_control_copy<_Base, _Types...>>; +struct _Deleted_move : _SMF_control_copy<_Base, _Types...> { // deleted move construction facade + using _Mybase = _SMF_control_copy<_Base, _Types...>; + using _Mybase::_Mybase; + + _Deleted_move() = default; + _Deleted_move(const _Deleted_move&) = default; + _Deleted_move(_Deleted_move&&) = delete; + _Deleted_move& operator=(const _Deleted_move&) = default; + _Deleted_move& operator=(_Deleted_move&&) = default; +}; + +template +using _SMF_control_move = + conditional_t...>, _SMF_control_copy<_Base, _Types...>, + conditional_t...>, _Non_trivial_move<_Base, _Types...>, + _Deleted_move<_Base, _Types...>>>; template struct _Non_trivial_copy_assign : _SMF_control_move<_Base, _Types...> { // non-trivial copy assignment facade diff --git a/stl/inc/xutility b/stl/inc/xutility index ee954bc9c69..ee38651f3ac 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -230,26 +230,19 @@ struct _Get_rebind_alias<_Ty, _Other, void_t; }; -template -_NODISCARD constexpr void* _Voidify_iter(_Iter _It) noexcept { - if constexpr (is_pointer_v<_Iter>) { - return const_cast(static_cast(_It)); - } else { - return const_cast(static_cast(_STD addressof(*_It))); - } -} - #if _HAS_CXX20 #ifdef __EDG__ // TRANSITION, DevCom-1691516 +// per LWG-3888 _EXPORT_STD template ()) _Ty(_STD declval<_Types>()...))>> + class = void_t(_STD declval<_Ty*>())) _Ty(_STD declval<_Types>()...))>> #else // ^^^ no workaround / workaround vvv +// per LWG-3888 _EXPORT_STD template ()) _Ty(_STD declval<_Types>()...))>* = nullptr> + void_t(_STD declval<_Ty*>())) _Ty(_STD declval<_Types>()...))>* = nullptr> #endif // TRANSITION, DevCom-1691516 constexpr _Ty* construct_at(_Ty* const _Location, _Types&&... _Args) noexcept( - noexcept(::new(_Voidify_iter(_Location)) _Ty(_STD forward<_Types>(_Args)...))) /* strengthened */ { - _MSVC_CONSTEXPR return ::new (_Voidify_iter(_Location)) _Ty(_STD forward<_Types>(_Args)...); + noexcept(::new(static_cast(_Location)) _Ty(_STD forward<_Types>(_Args)...))) /* strengthened */ { + _MSVC_CONSTEXPR return ::new (static_cast(_Location)) _Ty(_STD forward<_Types>(_Args)...); } #endif // _HAS_CXX20 @@ -262,13 +255,13 @@ _CONSTEXPR20 void _Construct_in_place(_Ty& _Obj, _Types&&... _Args) noexcept( } else #endif // _HAS_CXX20 { - ::new (_Voidify_iter(_STD addressof(_Obj))) _Ty(_STD forward<_Types>(_Args)...); + ::new (static_cast(_STD addressof(_Obj))) _Ty(_STD forward<_Types>(_Args)...); } } template void _Default_construct_in_place(_Ty& _Obj) noexcept(is_nothrow_default_constructible_v<_Ty>) { - ::new (_Voidify_iter(_STD addressof(_Obj))) _Ty; + ::new (static_cast(_STD addressof(_Obj))) _Ty; } template diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index 2d41f7f11b8..810f18c9d79 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -81,6 +81,10 @@ std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/unsync_deallocate_ma # Too many constexpr operations std/utilities/charconv/charconv.to.chars/integral.pass.cpp FAIL +std/utilities/template.bitset/bitset.members/left_shift_eq.pass.cpp FAIL +std/utilities/template.bitset/bitset.members/op_and_eq.pass.cpp FAIL +std/utilities/template.bitset/bitset.members/op_or_eq.pass.cpp FAIL +std/utilities/template.bitset/bitset.members/right_shift_eq.pass.cpp FAIL # libc++ tests strengthened assignment operators (not compatible with P2165R4: "Compatibility Between tuple, pair, And tuple-like Objects") std/utilities/tuple/tuple.tuple/tuple.assign/const_pair.pass.cpp FAIL @@ -125,6 +129,19 @@ std/strings/string.view/string.view.cons/from_range.pass.cpp FAIL std/strings/string.view/string.view.cons/from_string1.compile.fail.cpp FAIL std/strings/string.view/string.view.cons/from_string2.compile.fail.cpp FAIL +# libc++ doesn't implement LWG-3870 +std/utilities/memory/specialized.algorithms/specialized.construct/ranges_construct_at.pass.cpp FAIL +std/utilities/memory/specialized.algorithms/uninitialized.construct.default/ranges_uninitialized_default_construct.pass.cpp FAIL +std/utilities/memory/specialized.algorithms/uninitialized.construct.default/ranges_uninitialized_default_construct_n.pass.cpp FAIL +std/utilities/memory/specialized.algorithms/uninitialized.construct.value/ranges_uninitialized_value_construct.pass.cpp FAIL +std/utilities/memory/specialized.algorithms/uninitialized.construct.value/ranges_uninitialized_value_construct_n.pass.cpp FAIL +std/utilities/memory/specialized.algorithms/uninitialized.copy/ranges_uninitialized_copy.pass.cpp FAIL +std/utilities/memory/specialized.algorithms/uninitialized.copy/ranges_uninitialized_copy_n.pass.cpp FAIL +std/utilities/memory/specialized.algorithms/uninitialized.fill/ranges_uninitialized_fill.pass.cpp FAIL +std/utilities/memory/specialized.algorithms/uninitialized.fill.n/ranges_uninitialized_fill_n.pass.cpp FAIL +std/utilities/memory/specialized.algorithms/uninitialized.move/ranges_uninitialized_move.pass.cpp FAIL +std/utilities/memory/specialized.algorithms/uninitialized.move/ranges_uninitialized_move_n.pass.cpp FAIL + # libc++ doesn't implement P1957R2 "Converting from `T*` to `bool` should be considered narrowing" std/utilities/variant/variant.variant/variant.assign/conv.pass.cpp FAIL std/utilities/variant/variant.variant/variant.assign/T.pass.cpp FAIL @@ -919,13 +936,6 @@ std/localization/locale.categories/category.numeric/locale.nm.put/facet.num.put. # Not analyzed. These tests use characters that cannot be represented in legacy character encodings std/utilities/format/format.functions/ascii.pass.cpp FAIL -# Not analyzed. "constexpr evaluation hit maximum step limit; possible infinite loop?" -std/utilities/template.bitset/bitset.members/left_shift_eq.pass.cpp FAIL -std/utilities/template.bitset/bitset.members/op_and_eq.pass.cpp FAIL -std/utilities/template.bitset/bitset.members/op_or_eq.pass.cpp FAIL -std/utilities/template.bitset/bitset.members/right_shift_eq.pass.cpp FAIL -std/utilities/template.bitset/bitset.members/to_string.pass.cpp:1 FAIL - # Not analyzed std/algorithms/alg.modifying.operations/alg.random.sample/ranges_sample.pass.cpp FAIL std/algorithms/alg.modifying.operations/alg.rotate/ranges_rotate.pass.cpp FAIL diff --git a/tests/std/tests/Dev11_0920385_list_sort_allocator/test.cpp b/tests/std/tests/Dev11_0920385_list_sort_allocator/test.cpp index e3b01dad3f4..40e289d093b 100644 --- a/tests/std/tests/Dev11_0920385_list_sort_allocator/test.cpp +++ b/tests/std/tests/Dev11_0920385_list_sort_allocator/test.cpp @@ -282,7 +282,9 @@ int main() { test_1119194(); test_1184701(); test_LWG_2455(); +#if !_HAS_CXX20 // support removed in C++20 by P0619R4 test_allocator_construct_const(); +#endif // !_HAS_CXX20 } // Also test DevDiv-1119194 "The STL should handle allocators that aren't assignable". @@ -465,6 +467,7 @@ void test_LWG_2455() { } } +#if !_HAS_CXX20 // support removed in C++20 by P0619R4 void test_allocator_construct_const() { // Annex D actually requires the default allocator to const_cast here // See N4659 D.9 [depr.default.allocator]/6 @@ -476,3 +479,4 @@ void test_allocator_construct_const() { allocator_traits>::construct(alloc, exampleCptr, 1729); assert(example == 1729); } +#endif // !_HAS_CXX20 diff --git a/tests/std/tests/GH_000431_copy_move_family/test.cpp b/tests/std/tests/GH_000431_copy_move_family/test.cpp index f3f135b5466..9486d75d7f6 100644 --- a/tests/std/tests/GH_000431_copy_move_family/test.cpp +++ b/tests/std/tests/GH_000431_copy_move_family/test.cpp @@ -639,41 +639,6 @@ void test_algorithms(CopyFn copy_fn) { } } -template -void test_uninitialized_algorithms(CopyFn copy_fn) { - test_algorithms(copy_fn); - - { // Test const destination - int src[10] = {5, 7, 3, 4, 6, 4, 7, 1, 9, 5}; - int expected[10] = {5, 7, 3, 4, 6, 4, 7, 1, 9, 5}; - int dst[10]{}; - - copy_fn(begin(src), end(src), cbegin(dst)); - - assert(equal(begin(expected), end(expected), begin(dst), end(dst))); - } - - { // Test move_iterator with const destination - int src[10] = {5, 7, 3, 4, 6, 4, 7, 1, 9, 5}; - int expected[10] = {5, 7, 3, 4, 6, 4, 7, 1, 9, 5}; - int dst[10]{}; - - copy_fn(make_move_iterator(begin(src)), make_move_iterator(end(src)), cbegin(dst)); - - assert(equal(begin(expected), end(expected), begin(dst), end(dst))); - } - - { // Test vector with const destination - vector src = {3, 6, 4, 7, 3}; - vector expected = {3, 6, 4, 7, 3}; - vector dst = {0, 0, 0, 0, 0}; - - copy_fn(begin(src), end(src), cbegin(dst)); - - assert(equal(begin(expected), end(expected), begin(dst), end(dst))); - } -} - int main() { test_algorithms([](auto begin, auto end, auto out) { copy(begin, end, out); }); test_algorithms([](auto begin, auto end, auto out) { copy_n(begin, distance(begin, end), out); }); @@ -682,14 +647,12 @@ int main() { test_algorithms([](auto begin, auto end, auto out) { move(begin, end, out); }); test_algorithms([](auto begin, auto end, auto out) { move_backward(begin, end, next(out, distance(begin, end))); }); - test_uninitialized_algorithms([](auto begin, auto end, auto out) { uninitialized_copy(begin, end, out); }); - test_uninitialized_algorithms( - [](auto begin, auto end, auto out) { uninitialized_copy_n(begin, distance(begin, end), out); }); + test_algorithms([](auto begin, auto end, auto out) { uninitialized_copy(begin, end, out); }); + test_algorithms([](auto begin, auto end, auto out) { uninitialized_copy_n(begin, distance(begin, end), out); }); #if _HAS_CXX17 - test_uninitialized_algorithms([](auto begin, auto end, auto out) { uninitialized_move(begin, end, out); }); - test_uninitialized_algorithms( - [](auto begin, auto end, auto out) { uninitialized_move_n(begin, distance(begin, end), out); }); + test_algorithms([](auto begin, auto end, auto out) { uninitialized_move(begin, end, out); }); + test_algorithms([](auto begin, auto end, auto out) { uninitialized_move_n(begin, distance(begin, end), out); }); #endif // _HAS_CXX17 #ifdef __cpp_lib_concepts @@ -714,35 +677,35 @@ int main() { } }); - test_uninitialized_algorithms([](auto begin, auto end, auto out) { + test_algorithms([](auto begin, auto end, auto out) { ranges::uninitialized_copy(begin, end, out, next(out, distance(begin, end))); }); - test_uninitialized_algorithms( + test_algorithms( [](auto begin, auto end, auto out) { ranges::uninitialized_copy(begin, end, out, unreachable_sentinel); }); - test_uninitialized_algorithms([](auto begin, auto end, auto out) { + test_algorithms([](auto begin, auto end, auto out) { ranges::uninitialized_copy(begin, unreachable_sentinel, out, next(out, distance(begin, end))); }); - test_uninitialized_algorithms([](auto begin, auto end, auto out) { + test_algorithms([](auto begin, auto end, auto out) { ranges::uninitialized_copy_n(begin, distance(begin, end), out, next(out, distance(begin, end))); }); - test_uninitialized_algorithms([](auto begin, auto end, auto out) { + test_algorithms([](auto begin, auto end, auto out) { ranges::uninitialized_copy_n(begin, distance(begin, end), out, unreachable_sentinel); }); - test_uninitialized_algorithms([](auto begin, auto end, auto out) { + test_algorithms([](auto begin, auto end, auto out) { ranges::uninitialized_move(begin, end, out, next(out, distance(begin, end))); }); - test_uninitialized_algorithms( + test_algorithms( [](auto begin, auto end, auto out) { ranges::uninitialized_move(begin, end, out, unreachable_sentinel); }); - test_uninitialized_algorithms([](auto begin, auto end, auto out) { + test_algorithms([](auto begin, auto end, auto out) { ranges::uninitialized_move(begin, unreachable_sentinel, out, next(out, distance(begin, end))); }); - test_uninitialized_algorithms([](auto begin, auto end, auto out) { + test_algorithms([](auto begin, auto end, auto out) { ranges::uninitialized_move_n(begin, distance(begin, end), out, next(out, distance(begin, end))); }); - test_uninitialized_algorithms([](auto begin, auto end, auto out) { + test_algorithms([](auto begin, auto end, auto out) { ranges::uninitialized_move_n(begin, distance(begin, end), out, unreachable_sentinel); }); #endif // __cpp_lib_concepts diff --git a/tests/std/tests/GH_002992_unwrappable_iter_sent_pairs/test.compile.pass.cpp b/tests/std/tests/GH_002992_unwrappable_iter_sent_pairs/test.compile.pass.cpp index 8dca4b4a419..f038142c6df 100644 --- a/tests/std/tests/GH_002992_unwrappable_iter_sent_pairs/test.compile.pass.cpp +++ b/tests/std/tests/GH_002992_unwrappable_iter_sent_pairs/test.compile.pass.cpp @@ -29,7 +29,10 @@ void test_algorithms(Rng& rng) { (void) ranges::mismatch(rng, other); (void) ranges::mismatch(other, rng); - if constexpr (is_lvalue_reference_v> && ranges::forward_range) { + using range_ref_t = ranges::range_reference_t; + using range_deref_t = remove_reference_t; + if constexpr (is_lvalue_reference_v && !is_const_v && !is_volatile_v + && ranges::forward_range) { (void) ranges::uninitialized_copy(rng.begin(), rng.end(), other.begin(), other.end()); (void) ranges::uninitialized_copy(other.begin(), other.end(), rng.begin(), rng.end()); (void) ranges::uninitialized_copy(rng, other); diff --git a/tests/std/tests/P0088R3_variant/test.cpp b/tests/std/tests/P0088R3_variant/test.cpp index 7c71757d6cf..7471255c69c 100644 --- a/tests/std/tests/P0088R3_variant/test.cpp +++ b/tests/std/tests/P0088R3_variant/test.cpp @@ -7193,7 +7193,8 @@ namespace msvc { using std::variant::variant; }; - my_variant v1{42}, v2{3.14}; + my_variant v1{42}; + my_variant v2{3.14}; auto visitor1 = [](auto&& x) { return static_cast(x); }; assert(std::visit(visitor1, v1) == 42.0); assert(std::visit(visitor1, v2) == 3.14); @@ -7850,6 +7851,92 @@ namespace msvc { #endif // _HAS_CXX20 } } // namespace gh2770 + + namespace assign_cv { + template + struct TypeIdentityImpl { + using type = T; + }; + template + using TypeIdentity = typename TypeIdentityImpl::type; + + struct CvAssignable { + CvAssignable() = default; + CvAssignable(const CvAssignable&) = default; + CvAssignable(CvAssignable&&) = default; + CvAssignable& operator=(const CvAssignable&) = default; + CvAssignable& operator=(CvAssignable&&) = default; + + template + CvAssignable(const volatile TypeIdentity&) noexcept {} + template + CvAssignable(const volatile TypeIdentity&&) noexcept {} + + template + constexpr CvAssignable& operator=(const volatile TypeIdentity&) noexcept { + return *this; + } + template + constexpr CvAssignable& operator=(const volatile TypeIdentity&&) noexcept { + return *this; + } + + template + constexpr const volatile CvAssignable& operator=(const volatile TypeIdentity&) const volatile noexcept { + return *this; + } + template + constexpr const volatile CvAssignable& operator=(const volatile TypeIdentity&&) const volatile noexcept { + return *this; + } + }; + + void run_test() { + using std::swap; + { + std::variant oc{}; + oc.emplace<0>(0); + STATIC_ASSERT(!std::is_copy_assignable_v); + STATIC_ASSERT(!std::is_move_assignable_v); + STATIC_ASSERT(!std::is_swappable_v); + + std::variant ov{}; + std::variant ov2{}; + ov.emplace<0>(0); + swap(ov, ov); + ov = ov2; + ov = std::move(ov2); + + std::variant ocv{}; + ocv.emplace<0>(0); + STATIC_ASSERT(!std::is_copy_assignable_v); + STATIC_ASSERT(!std::is_move_assignable_v); + STATIC_ASSERT(!std::is_swappable_v); + } + { + std::variant oc{}; + std::variant oc2{}; + oc.emplace<0>(CvAssignable{}); + swap(oc, oc); + oc = oc2; + oc = std::move(oc2); + + std::variant ov{}; + std::variant ov2{}; + ov.emplace<0>(CvAssignable{}); + swap(ov, ov); + ov = ov2; + ov = std::move(ov2); + + std::variant ocv{}; + std::variant ocv2{}; + ocv.emplace<0>(CvAssignable{}); + swap(ocv, ocv); + ocv = ocv2; + ocv = std::move(ocv2); + } + } + } // namespace assign_cv } // namespace msvc int main() { @@ -7916,6 +8003,7 @@ int main() { msvc::vso492097::run_test(); msvc::DevCom1031281::run_test(); msvc::gh2770::run_test(); + msvc::assign_cv::run_test(); } #else // ^^^ not x86 or not /analyze / x86 /analyze vvv int main() {} diff --git a/tests/std/tests/P0220R1_optional/test.cpp b/tests/std/tests/P0220R1_optional/test.cpp index 77d3497fde1..fc6537f9ff9 100644 --- a/tests/std/tests/P0220R1_optional/test.cpp +++ b/tests/std/tests/P0220R1_optional/test.cpp @@ -8237,6 +8237,92 @@ namespace msvc { testMove(); } } // namespace gh2458 + + namespace assign_cv { + template + struct TypeIdentityImpl { + using type = T; + }; + template + using TypeIdentity = typename TypeIdentityImpl::type; + + struct CvAssignable { + CvAssignable() = default; + CvAssignable(const CvAssignable&) = default; + CvAssignable(CvAssignable&&) = default; + CvAssignable& operator=(const CvAssignable&) = default; + CvAssignable& operator=(CvAssignable&&) = default; + + template + CvAssignable(const volatile TypeIdentity&) noexcept {} + template + CvAssignable(const volatile TypeIdentity&&) noexcept {} + + template + constexpr CvAssignable& operator=(const volatile TypeIdentity&) noexcept { + return *this; + } + template + constexpr CvAssignable& operator=(const volatile TypeIdentity&&) noexcept { + return *this; + } + + template + constexpr const volatile CvAssignable& operator=(const volatile TypeIdentity&) const volatile noexcept { + return *this; + } + template + constexpr const volatile CvAssignable& operator=(const volatile TypeIdentity&&) const volatile noexcept { + return *this; + } + }; + + void run_test() { + using std::swap; + { + std::optional oc{}; + oc.emplace(0); + STATIC_ASSERT(!std::is_copy_assignable_v); + STATIC_ASSERT(!std::is_move_assignable_v); + STATIC_ASSERT(!std::is_swappable_v); + + std::optional ov{}; + std::optional ov2{}; + ov.emplace(0); + swap(ov, ov); + ov = ov2; + ov = std::move(ov2); + + std::optional ocv{}; + ocv.emplace(0); + STATIC_ASSERT(!std::is_copy_assignable_v); + STATIC_ASSERT(!std::is_move_assignable_v); + STATIC_ASSERT(!std::is_swappable_v); + } + { + std::optional oc{}; + std::optional oc2{}; + oc.emplace(CvAssignable{}); + swap(oc, oc); + oc = oc2; + oc = std::move(oc2); + + std::optional ov{}; + std::optional ov2{}; + ov.emplace(CvAssignable{}); + swap(ov, ov); + ov = ov2; + ov = std::move(ov2); + + std::optional ocv{}; + std::optional ocv2{}; + ocv.emplace(CvAssignable{}); + swap(ocv, ocv); + ocv = ocv2; + ocv = std::move(ocv2); + } + } + } // namespace assign_cv } // namespace msvc int main() { @@ -8339,4 +8425,6 @@ int main() { msvc::vso614907::run_test(); msvc::gh2458::run_test(); + + msvc::assign_cv::run_test(); } 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 4f7aa4dcdad..f79d24527f1 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 @@ -36,9 +36,13 @@ inline constexpr bool can_construct_at = [] { template constexpr bool construct_at_noexcept() { - constexpr bool result = noexcept(construct_at(declval(), declval()...)); - static_assert(noexcept(ranges::construct_at(declval(), declval()...)) == result); - return result; + if constexpr (can_construct_at) { + constexpr bool result = noexcept(construct_at(declval(), declval()...)); + static_assert(noexcept(ranges::construct_at(declval(), declval()...)) == result); + return result; + } else { + return false; + } } template @@ -62,7 +66,11 @@ inline constexpr bool can_construct_at = can_construct_at_impl constexpr bool construct_at_noexcept() { - return noexcept(construct_at(declval(), declval()...)); + if constexpr (can_construct_at) { + return noexcept(construct_at(declval(), declval()...)); + } else { + return false; + } } template @@ -72,17 +80,18 @@ constexpr bool destroy_at_noexcept() { #endif // __cpp_lib_concepts static_assert(can_construct_at); -static_assert(can_construct_at); -static_assert(can_construct_at); -static_assert(can_construct_at); static_assert(can_construct_at); -static_assert(can_construct_at); -static_assert(can_construct_at); -static_assert(can_construct_at); static_assert(can_construct_at); -static_assert(can_construct_at); -static_assert(can_construct_at); -static_assert(can_construct_at); +// per LWG-3888 +static_assert(!can_construct_at); +static_assert(!can_construct_at); +static_assert(!can_construct_at); +static_assert(!can_construct_at); +static_assert(!can_construct_at); +static_assert(!can_construct_at); +static_assert(!can_construct_at); +static_assert(!can_construct_at); +static_assert(!can_construct_at); struct X {}; @@ -100,9 +109,10 @@ struct indestructible { }; static_assert(can_construct_at); -static_assert(can_construct_at); -static_assert(can_construct_at); -static_assert(can_construct_at); +// per LWG-3888 +static_assert(!can_construct_at); +static_assert(!can_construct_at); +static_assert(!can_construct_at); static_assert(can_construct_at); static_assert(can_construct_at); @@ -118,11 +128,13 @@ static_assert(!can_construct_at); // The following static_asserts test our strengthening of noexcept static_assert(construct_at_noexcept()); -static_assert(construct_at_noexcept()); -static_assert(construct_at_noexcept()); -static_assert(construct_at_noexcept()); +// per LWG-3888 +static_assert(!construct_at_noexcept()); +static_assert(!construct_at_noexcept()); +static_assert(!construct_at_noexcept()); static_assert(!construct_at_noexcept()); +// per LWG-3888 static_assert(!construct_at_noexcept()); static_assert(!construct_at_noexcept()); static_assert(!construct_at_noexcept()); @@ -173,20 +185,6 @@ void test_runtime(const Ty& val) { assert(*asPtrTy == val); ranges::destroy_at(asPtrTy); #endif // __cpp_lib_concepts - - // test voidify: - const auto asCv = static_cast(asPtrTy); - memset(storage, 42, sizeof(Ty)); - assert(asPtrTy == construct_at(asCv, val)); - assert(const_cast(*asCv) == val); - destroy_at(asCv); - -#ifdef __cpp_lib_concepts - memset(storage, 42, sizeof(Ty)); - assert(asPtrTy == ranges::construct_at(asCv, val)); - assert(const_cast(*asCv) == val); - ranges::destroy_at(asCv); -#endif // __cpp_lib_concepts } template @@ -195,21 +193,20 @@ void test_array(const T& val) { (void) val; alignas(T) unsigned char storage[sizeof(T) * N]; - using U = conditional_t, const volatile T, T>; - const auto ptr = reinterpret_cast(storage); + const auto ptr = reinterpret_cast(storage); for (auto i = 0; i < N; ++i) { construct_at(ptr + i, val); } - destroy_at(reinterpret_cast(ptr)); + destroy_at(reinterpret_cast(ptr)); #ifdef __cpp_lib_concepts for (auto i = 0; i < N; ++i) { ranges::construct_at(ptr + i, val); } - ranges::destroy_at(reinterpret_cast(ptr)); + ranges::destroy_at(reinterpret_cast(ptr)); #endif // __cpp_lib_concepts } @@ -522,6 +519,114 @@ constexpr void test_compiletime_operators() { } static_assert((test_compiletime_operators(), true)); +#ifdef __cpp_lib_concepts +// Also test LWG-3888 Most ranges uninitialized memory algorithms are underconstrained +template +concept CanUninitializedDefaultConstruct = requires(Rng& r) { ranges::uninitialized_default_construct(r); }; + +template +concept CanUninitializedDefaultConstructN = + requires(It&& i) { ranges::uninitialized_default_construct_n(forward(i), iter_difference_t{}); }; + +template +concept CanUninitializedValueConstruct = requires(Rng& r) { ranges::uninitialized_value_construct(r); }; + +template +concept CanUninitializedValueConstructN = + requires(It&& i) { ranges::uninitialized_value_construct_n(forward(i), iter_difference_t{}); }; + +template +concept CanUninitializedFill = requires(Rng& r, const T& t) { ranges::uninitialized_fill(r, t); }; + +template +concept CanUninitializedFillN = + requires(It&& i, const T& t) { ranges::uninitialized_fill_n(forward(i), iter_difference_t{}, t); }; + +template +concept CanUninitializedCopy = requires(InRng& ri, OutRng& ro) { ranges::uninitialized_copy(ri, ro); }; + +template +concept CanUninitializedCopyN = + requires(InIt&& ii, OutIt&& io, S&& s) { + ranges::uninitialized_copy_n(forward(ii), iter_difference_t{}, forward(io), forward(s)); + }; + +template +concept CanUninitializedMove = requires(InRng& ri, OutRng& ro) { ranges::uninitialized_move(ri, ro); }; + +template +concept CanUninitializedMoveN = + requires(InIt&& ii, OutIt&& io, S&& s) { + ranges::uninitialized_move_n(forward(ii), iter_difference_t{}, forward(io), forward(s)); + }; + +template +concept CanDestroy = requires(Rng&& r) { ranges::destroy(forward(r)); }; + +template +concept CanDestroyN = requires(It&& i) { ranges::destroy_n(forward(i), iter_difference_t{}); }; + +static_assert(CanUninitializedDefaultConstruct); +static_assert(!CanUninitializedDefaultConstruct); +static_assert(!CanUninitializedDefaultConstruct); +static_assert(!CanUninitializedDefaultConstruct); + +static_assert(CanUninitializedDefaultConstructN); +static_assert(!CanUninitializedDefaultConstructN); +static_assert(!CanUninitializedDefaultConstructN); +static_assert(!CanUninitializedDefaultConstructN); + +static_assert(CanUninitializedValueConstruct); +static_assert(!CanUninitializedValueConstruct); +static_assert(!CanUninitializedValueConstruct); +static_assert(!CanUninitializedValueConstruct); + +static_assert(CanUninitializedValueConstructN); +static_assert(!CanUninitializedValueConstructN); +static_assert(!CanUninitializedValueConstructN); +static_assert(!CanUninitializedValueConstructN); + +static_assert(CanUninitializedFill); +static_assert(!CanUninitializedFill); +static_assert(!CanUninitializedFill); +static_assert(!CanUninitializedFill); + +static_assert(CanUninitializedFillN); +static_assert(!CanUninitializedFillN); +static_assert(!CanUninitializedFillN); +static_assert(!CanUninitializedFillN); + +static_assert(CanUninitializedCopy); +static_assert(!CanUninitializedCopy); +static_assert(!CanUninitializedCopy); +static_assert(!CanUninitializedCopy); + +static_assert(CanUninitializedCopyN); +static_assert(!CanUninitializedCopyN); +static_assert(!CanUninitializedCopyN); +static_assert(!CanUninitializedCopyN); + +static_assert(CanUninitializedMove); +static_assert(!CanUninitializedMove); +static_assert(!CanUninitializedMove); +static_assert(!CanUninitializedMove); + +static_assert(CanUninitializedMoveN); +static_assert(!CanUninitializedMoveN); +static_assert(!CanUninitializedMoveN); +static_assert(!CanUninitializedMoveN); + +static_assert(CanDestroy); +static_assert(!CanDestroy); +static_assert(!CanDestroy); +static_assert(!CanDestroy); + +static_assert(CanDestroyN); +static_assert(!CanDestroyN); +static_assert(!CanDestroyN); +static_assert(!CanDestroyN); +#endif // __cpp_lib_concepts + int main() { test_runtime(1234); test_runtime(string("hello world")); diff --git a/tests/std/tests/P0896R4_common_iterator/test.cpp b/tests/std/tests/P0896R4_common_iterator/test.cpp index d1736b99cfd..ac88a54358b 100644 --- a/tests/std/tests/P0896R4_common_iterator/test.cpp +++ b/tests/std/tests/P0896R4_common_iterator/test.cpp @@ -1,6 +1,12 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +#pragma warning(disable : 5215) // volatile function arguments are deprecated in C++20 + +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wdeprecated-volatile" // volatile function arguments are deprecated in C++20 +#endif // __clang__ + #include #include #include @@ -332,6 +338,84 @@ void test_non_trivially_destructible_type() { // COMPILE-ONLY common_iterator it; } +struct VolatileSentinel { + VolatileSentinel() = default; + VolatileSentinel(const VolatileSentinel&) = default; + VolatileSentinel(VolatileSentinel&&) = default; + VolatileSentinel& operator=(const VolatileSentinel&) = default; + VolatileSentinel& operator=(VolatileSentinel&&) = default; + + constexpr explicit VolatileSentinel(const char* p) noexcept : ptr_{p} {} + + template + constexpr VolatileSentinel(const volatile type_identity_t& other) noexcept : ptr_{other.ptr_} {} + template + constexpr VolatileSentinel(const volatile type_identity_t&& other) noexcept : ptr_{other.ptr_} {} + + template + VolatileSentinel& operator=(volatile type_identity_t& rhs) noexcept { + ptr_ = rhs.ptr_; + return *this; + } + template + VolatileSentinel& operator=(volatile type_identity_t&& rhs) noexcept { + ptr_ = rhs.ptr_; + return *this; + } + template + VolatileSentinel& operator=(const volatile type_identity_t& rhs) noexcept { + ptr_ = rhs.ptr_; + return *this; + } + template + VolatileSentinel& operator=(const volatile type_identity_t&& rhs) noexcept { + ptr_ = rhs.ptr_; + return *this; + } + + template + volatile VolatileSentinel& operator=(const volatile type_identity_t& rhs) volatile noexcept { + ptr_ = rhs.ptr_; + return *this; + } + template + volatile VolatileSentinel& operator=(const volatile type_identity_t&& rhs) volatile noexcept { + ptr_ = rhs.ptr_; + return *this; + } + + friend constexpr bool operator==(const char* const lhs, VolatileSentinel rhs) noexcept { + return lhs == rhs.ptr_; + } + + friend constexpr auto operator-(const char* const lhs, VolatileSentinel rhs) noexcept { + return lhs - rhs.ptr_; + } + + friend constexpr auto operator-(VolatileSentinel lhs, const char* const rhs) noexcept { + return lhs.ptr_ - rhs; + } + + const char* ptr_ = nullptr; +}; + +// constexpr-incompatible +void test_volatile() { + using std::swap; + using CommonIt = common_iterator; + + CommonIt it{static_cast(nullptr)}; + CommonIt se{VolatileSentinel{static_cast(nullptr)}}; + + assert(it == se); + assert(it - se == 0); + assert(se - it == 0); + + swap(it, it); + it = se; + it = move(se); +} + int main() { with_writable_iterators::call(); static_assert(with_writable_iterators::call()); @@ -344,4 +428,6 @@ int main() { test_lwg_3574(); static_assert(test_lwg_3574()); + + test_volatile(); // constexpr-incompatible } diff --git a/tests/std/tests/P0896R4_views_single/test.cpp b/tests/std/tests/P0896R4_views_single/test.cpp index 54fc7abfb7c..2c2ad638519 100644 --- a/tests/std/tests/P0896R4_views_single/test.cpp +++ b/tests/std/tests/P0896R4_views_single/test.cpp @@ -170,6 +170,72 @@ void test_non_trivially_destructible_type() { // COMPILE-ONLY (void) views::single(non_trivially_destructible{}); } +struct VolatileConstructible { + VolatileConstructible() = default; + VolatileConstructible(const VolatileConstructible&) = default; + VolatileConstructible(VolatileConstructible&&) = default; + VolatileConstructible& operator=(const VolatileConstructible&) = default; + VolatileConstructible& operator=(VolatileConstructible&&) = default; + + template + constexpr VolatileConstructible(const volatile type_identity_t&) noexcept {} + template + constexpr VolatileConstructible(const volatile type_identity_t&&) noexcept {} +}; + +struct ConstSelection { + ConstSelection() = default; + ConstSelection(const ConstSelection&) = default; + ConstSelection(ConstSelection&&) = default; + ConstSelection& operator=(const ConstSelection&) = default; + ConstSelection& operator=(ConstSelection&&) = default; + + constexpr explicit ConstSelection(int x) noexcept : value{x} {} + + template + constexpr const ConstSelection& operator=(const type_identity_t&) const noexcept { + return *this; + } + + int value = 0; +}; + +static_assert(is_trivially_copy_assignable_v>); +static_assert(!is_trivially_copy_assignable_v>); + +constexpr bool test_cv() { + { + ranges::single_view sv{}; + ranges::single_view sv2{}; + sv = sv2; + sv = move(sv2); + } + { + ranges::single_view svv{}; + ranges::single_view svv2{}; + svv = svv2; + svv = move(svv2); + } + { + [[maybe_unused]] ranges::single_view svc{}; + [[maybe_unused]] ranges::single_view svcv{}; + } + { + ranges::single_view svx{in_place, 0}; + ranges::single_view svy{in_place, 42}; + svy = svx; + assert(svy.front().value == 0); + } + { + ranges::single_view scvx{in_place, 0}; + ranges::single_view scvy{in_place, 42}; + scvy = scvx; + assert(scvy.front().value == 42); + } + + return true; +} + int main() { static_assert(test_one_type(42, 42)); test_one_type(42, 42); @@ -179,4 +245,7 @@ int main() { test_one_type(only_copy_constructible{42}, 42); test_one_type(string{"Hello, World!"}, "Hello, World!"); + + static_assert(test_cv()); + assert(test_cv()); } diff --git a/tests/std/tests/VSO_0000000_instantiate_iterators_misc/test.compile.pass.cpp b/tests/std/tests/VSO_0000000_instantiate_iterators_misc/test.compile.pass.cpp index 0e6909d701f..e48746e4e1d 100644 --- a/tests/std/tests/VSO_0000000_instantiate_iterators_misc/test.compile.pass.cpp +++ b/tests/std/tests/VSO_0000000_instantiate_iterators_misc/test.compile.pass.cpp @@ -1274,7 +1274,8 @@ template void regex_token_iterator_test_impl() { using it_type = typename RegexTokenIterator::value_type::iterator; int submatches[10] = {0}; - it_type start{}, finish{}; + it_type start{}; + it_type finish{}; typename RegexTokenIterator::regex_type rgx{}; RegexTokenIterator rti0(start, finish, rgx, submatches); } diff --git a/tests/std/tests/VSO_0180469_fill_family/test.cpp b/tests/std/tests/VSO_0180469_fill_family/test.cpp index 52bc0a41a5d..d6898732bca 100644 --- a/tests/std/tests/VSO_0180469_fill_family/test.cpp +++ b/tests/std/tests/VSO_0180469_fill_family/test.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include using namespace std; @@ -51,6 +52,19 @@ void test_case_fill(CharT value, Func fillCall) { } } +template +void test_fill_volatile() { + const CharT testCases[] = {cast(-100), cast(-1), cast(0), cast(1), cast(100)}; + + for (CharT testCase : testCases) { + test_case_fill(testCase, + [](BuffT* buff, CharT value, size_t start, size_t end) { fill(buff + start, buff + end, value); }); + + test_case_fill(testCase, + [](BuffT* buff, CharT value, size_t start, size_t end) { fill_n(buff + start, end - start, value); }); + } +} + template void test_fill() { const CharT testCases[] = {cast(-100), cast(-1), cast(0), cast(1), cast(100)}; @@ -133,9 +147,9 @@ int main() { test_fill(); test_fill(); - test_fill(); // Test GH-1183 + test_fill_volatile(); // Test GH-1183 #ifdef __cpp_lib_byte - test_fill(); // Test GH-1556 + test_fill_volatile(); // Test GH-1556 #endif // __cpp_lib_byte test_uninitialized_fill(