diff --git a/stl/inc/optional b/stl/inc/optional index 151ddade147..4a0f521fa20 100644 --- a/stl/inc/optional +++ b/stl/inc/optional @@ -75,7 +75,7 @@ struct _Optional_destruct_base { // either contains a value of _Ty or is empty ( constexpr explicit _Optional_destruct_base(in_place_t, _Types&&... _Args) : _Value(_STD forward<_Types>(_Args)...), _Has_value{true} {} // initialize contained value with _Args... - void reset() noexcept { + _CONSTEXPR20 void reset() noexcept { _Has_value = false; } }; @@ -88,7 +88,7 @@ struct _Optional_destruct_base<_Ty, false> { // either contains a value of _Ty o }; bool _Has_value; - ~_Optional_destruct_base() noexcept { + _CONSTEXPR20 ~_Optional_destruct_base() noexcept { if (_Has_value) { _Destroy_in_place(_Value); } @@ -105,7 +105,7 @@ struct _Optional_destruct_base<_Ty, false> { // either contains a value of _Ty o _Optional_destruct_base& operator=(const _Optional_destruct_base&) = default; _Optional_destruct_base& operator=(_Optional_destruct_base&&) = default; - void reset() noexcept { + _CONSTEXPR20 void reset() noexcept { if (_Has_value) { _Destroy_in_place(_Value); _Has_value = false; @@ -119,7 +119,8 @@ struct _Optional_construct_base : _Optional_destruct_base<_Ty> { using _Optional_destruct_base<_Ty>::_Optional_destruct_base; template - _Ty& _Construct(_Types&&... _Args) { // transition from the empty to the value-containing state + _CONSTEXPR20 _Ty& _Construct(_Types&&... _Args) { + // transition from the empty to the value-containing state _STL_INTERNAL_CHECK(!this->_Has_value); _Construct_in_place(this->_Value, _STD forward<_Types>(_Args)...); this->_Has_value = true; @@ -127,7 +128,7 @@ struct _Optional_construct_base : _Optional_destruct_base<_Ty> { } template - void _Assign(_Ty2&& _Right) { // assign / initialize the contained value from _Right + _CONSTEXPR20 void _Assign(_Ty2&& _Right) { // assign / initialize the contained value from _Right if (this->_Has_value) { this->_Value = _STD forward<_Ty2>(_Right); } else { @@ -136,7 +137,7 @@ struct _Optional_construct_base : _Optional_destruct_base<_Ty> { } template - void _Construct_from(_Self&& _Right) noexcept( + _CONSTEXPR20 void _Construct_from(_Self&& _Right) noexcept( is_nothrow_constructible_v<_Ty, decltype((_STD forward<_Self>(_Right)._Value))>) { // initialize contained value from _Right iff it contains a value if (_Right._Has_value) { @@ -145,7 +146,7 @@ struct _Optional_construct_base : _Optional_destruct_base<_Ty> { } template - void _Assign_from(_Self&& _Right) noexcept( + _CONSTEXPR20 void _Assign_from(_Self&& _Right) noexcept( is_nothrow_constructible_v<_Ty, decltype((_STD forward<_Self>(_Right)._Value))>&& is_nothrow_assignable_v<_Ty&, decltype((_STD forward<_Self>(_Right)._Value))>) { // assign/initialize/destroy contained value from _Right @@ -208,7 +209,7 @@ public: #if _HAS_CONDITIONAL_EXPLICIT template , is_constructible<_Ty, const _Ty2&>>, int> = 0> - explicit(!is_convertible_v) optional(const optional<_Ty2>& _Right) { + _CONSTEXPR20 explicit(!is_convertible_v) optional(const optional<_Ty2>& _Right) { if (_Right) { this->_Construct(*_Right); } @@ -234,7 +235,7 @@ public: #if _HAS_CONDITIONAL_EXPLICIT template , is_constructible<_Ty, _Ty2>>, int> = 0> - explicit(!is_convertible_v<_Ty2, _Ty>) optional(optional<_Ty2>&& _Right) { + _CONSTEXPR20 explicit(!is_convertible_v<_Ty2, _Ty>) optional(optional<_Ty2>&& _Right) { if (_Right) { this->_Construct(_STD move(*_Right)); } @@ -258,7 +259,7 @@ public: } #endif // ^^^ !_HAS_CONDITIONAL_EXPLICIT ^^^ - optional& operator=(nullopt_t) noexcept { + _CONSTEXPR20 optional& operator=(nullopt_t) noexcept { reset(); return *this; } @@ -267,7 +268,7 @@ public: negation, is_same<_Ty, decay_t<_Ty2>>>>, is_constructible<_Ty, _Ty2>, is_assignable<_Ty&, _Ty2>>, int> = 0> - optional& operator=(_Ty2&& _Right) { + _CONSTEXPR20 optional& operator=(_Ty2&& _Right) { this->_Assign(_STD forward<_Ty2>(_Right)); return *this; } @@ -281,7 +282,7 @@ public: template , is_constructible<_Ty, const _Ty2&>, is_assignable<_Ty&, const _Ty2&>>, int> = 0> - optional& operator=(const optional<_Ty2>& _Right) { + _CONSTEXPR20 optional& operator=(const optional<_Ty2>& _Right) { if (_Right) { this->_Assign(*_Right); } else { @@ -294,7 +295,7 @@ public: template , is_constructible<_Ty, _Ty2>, is_assignable<_Ty&, _Ty2>>, int> = 0> - optional& operator=(optional<_Ty2>&& _Right) { + _CONSTEXPR20 optional& operator=(optional<_Ty2>&& _Right) { if (_Right) { this->_Assign(_STD move(*_Right)); } else { @@ -305,19 +306,20 @@ public: } template - _Ty& emplace(_Types&&... _Args) { + _CONSTEXPR20 _Ty& emplace(_Types&&... _Args) { reset(); return this->_Construct(_STD forward<_Types>(_Args)...); } template &, _Types...>, int> = 0> - _Ty& emplace(initializer_list<_Elem> _Ilist, _Types&&... _Args) { + _CONSTEXPR20 _Ty& emplace(initializer_list<_Elem> _Ilist, _Types&&... _Args) { reset(); return this->_Construct(_Ilist, _STD forward<_Types>(_Args)...); } - void swap(optional& _Right) noexcept(is_nothrow_move_constructible_v<_Ty>&& is_nothrow_swappable_v<_Ty>) { + _CONSTEXPR20 void swap(optional& _Right) noexcept( + is_nothrow_move_constructible_v<_Ty>&& is_nothrow_swappable_v<_Ty>) { static_assert(is_move_constructible_v<_Ty>, "optional::swap requires T to be move constructible (N4828 [optional.swap]/1)."); static_assert(!is_move_constructible_v<_Ty> || is_swappable_v<_Ty>, @@ -654,7 +656,7 @@ _NODISCARD constexpr compare_three_way_result_t<_Ty1, _Ty2> #endif // __cpp_lib_concepts template && is_swappable_v<_Ty>, int> = 0> -void swap(optional<_Ty>& _Left, optional<_Ty>& _Right) noexcept(noexcept(_Left.swap(_Right))) { +_CONSTEXPR20 void swap(optional<_Ty>& _Left, optional<_Ty>& _Right) noexcept(noexcept(_Left.swap(_Right))) { _Left.swap(_Right); } diff --git a/stl/inc/variant b/stl/inc/variant index 8ce0a7f4c35..6a21afec4c0 100644 --- a/stl/inc/variant +++ b/stl/inc/variant @@ -434,7 +434,7 @@ public: _Variant_storage<_Rest...> _Tail; }; - _Variant_storage_() noexcept {} // no initialization (no active member) + _CONSTEXPR20 _Variant_storage_() noexcept {} // no initialization (no active member) template constexpr explicit _Variant_storage_(integral_constant, _Types&&... _Args) noexcept( @@ -469,11 +469,12 @@ public: _Variant_storage<_Rest...> _Tail; }; - ~_Variant_storage_() noexcept { // explicitly non-trivial destructor (which would otherwise be defined as deleted - // since the class has a variant member with a non-trivial destructor) + _CONSTEXPR20 ~_Variant_storage_() noexcept { + // explicitly non-trivial destructor (which would otherwise be defined as deleted + // since the class has a variant member with a non-trivial destructor) } - _Variant_storage_() noexcept {} // no initialization (no active member) + _CONSTEXPR20 _Variant_storage_() noexcept {} // no initialization (no active member) template constexpr explicit _Variant_storage_(integral_constant, _Types&&... _Args) noexcept( @@ -525,11 +526,12 @@ public: _Variant_storage<_Rest...> _Tail; }; - ~_Variant_storage_() noexcept { // explicitly non-trivial destructor (which would otherwise be defined as deleted - // since the class has a variant member with a non-trivial destructor) + _CONSTEXPR20 ~_Variant_storage_() noexcept { + // explicitly non-trivial destructor (which would otherwise be defined as deleted + // since the class has a variant member with a non-trivial destructor) } - _Variant_storage_() noexcept {} // no initialization (no active member) + _CONSTEXPR20 _Variant_storage_() noexcept {} // no initialization (no active member) template constexpr explicit _Variant_storage_(integral_constant, _Types&&... _Args) noexcept( @@ -754,13 +756,13 @@ struct _Variant_construct_visitor { // visitor that constructs the same alternat _Variant_base<_Types...>& _Self; template - void operator()(_Tagged<_Ty, _Idx> _Source) const noexcept(disjunction_v, - is_nothrow_constructible, _Ty>>) { // initialize _Idx-th item in _Self from _Source - // pre: _Self.valueless_by_exception() + _CONSTEXPR20 void operator()(_Tagged<_Ty, _Idx> _Source) const noexcept( + disjunction_v, is_nothrow_constructible, _Ty>>) { + // initialize _Idx-th item in _Self from _Source + _STL_INTERNAL_CHECK(_Self.valueless_by_exception()); (void) _Source; // TRANSITION, DevCom-1004719 if constexpr (_Idx != variant_npos) { - auto& _Target = _Variant_raw_get<_Idx>(_Self._Storage()); - _Construct_in_place(_Target, static_cast<_Ty&&>(_Source._Val)); + _Construct_in_place(_Self._Storage(), integral_constant{}, static_cast<_Ty&&>(_Source._Val)); _Self._Set_index(_Idx); } } @@ -775,31 +777,33 @@ struct _Variant_assign_visitor { // visitor that implements assignment for varia _Variant_base<_Types...>& _Self; template - void operator()(_Tagged<_Ty, _Idx> _Source) const noexcept(disjunction_v, - conjunction&, _Ty>, - is_nothrow_constructible<_Remove_cvref_t<_Ty>, _Ty>>>) { + _CONSTEXPR20 void operator()(_Tagged<_Ty, _Idx> _Source) const + noexcept(disjunction_v, + conjunction&, _Ty>, + is_nothrow_constructible<_Remove_cvref_t<_Ty>, _Ty>>>) { // assign the _Idx-th alternative of _Self from _Source if constexpr (_Idx == variant_npos) { // assign from valueless _Source (void) _Source; // TRANSITION, DevCom-1004719 _Self._Reset(); } else { - auto& _Target = _Variant_raw_get<_Idx>(_Self._Storage()); if (_Self._Which == _Idx) { // same alternative: assign directly - _Target = static_cast<_Ty&&>(_Source._Val); + auto& _Target = _Variant_raw_get<_Idx>(_Self._Storage()); + _Target = static_cast<_Ty&&>(_Source._Val); } else { // different alternative if constexpr (is_lvalue_reference_v<_Ty>) { // RHS is an lvalue: copy - if constexpr (_Variant_should_directly_construct_v<_Remove_cvref_t<_Ty>, - _Ty>) { // copy is nothrow or move throws; construct in place + if constexpr (_Variant_should_directly_construct_v<_Remove_cvref_t<_Ty>, _Ty>) { + // copy is nothrow or move throws; construct in place _Self._Reset(); - _Construct_in_place(_Target, _Source._Val); + _Construct_in_place(_Self._Storage(), integral_constant{}, _Source._Val); } else { // copy throws and move does not; move from a temporary copy auto _Temp = _Source._Val; _Self._Reset(); - _Construct_in_place(_Target, _STD move(_Temp)); + _Construct_in_place(_Self._Storage(), integral_constant{}, _STD move(_Temp)); } } else { // RHS is an rvalue: move _Self._Reset(); - _Construct_in_place(_Target, static_cast<_Ty&&>(_Source._Val)); + _Construct_in_place( + _Self._Storage(), integral_constant{}, static_cast<_Ty&&>(_Source._Val)); } _Self._Set_index(_Idx); @@ -808,9 +812,8 @@ struct _Variant_assign_visitor { // visitor that implements assignment for varia } }; -template -class _Variant_base - : private _Variant_storage<_Types...> { // Associate an integral discriminator with a _Variant_storage +template // Associate an integral discriminator with a _Variant_storage +class _Variant_base : private _Variant_storage<_Types...> { public: using _Index_t = _Variant_index_t; static constexpr auto _Invalid_index = static_cast<_Index_t>(-1); @@ -830,7 +833,8 @@ public: return _STD move(*this); } - _Variant_base() noexcept : _Storage_t{}, _Which{_Invalid_index} {} // initialize to the value-less state + // initialize to the value-less state + _CONSTEXPR20 _Variant_base() noexcept : _Storage_t{}, _Which{_Invalid_index} {} template , _Idx>, _UTypes...>, int> = 0> @@ -847,14 +851,14 @@ public: // index of the contained alternative or variant_npos if valueless_by_exception return static_cast(_Which); } - void _Set_index(const size_t _Idx) noexcept { + _CONSTEXPR20 void _Set_index(const size_t _Idx) noexcept { // record _Idx as the active alternative // pre: the active alternative of *this is _Idx _Which = static_cast<_Index_t>(_Idx); } template - void _Destroy() noexcept { + _CONSTEXPR20 void _Destroy() noexcept { // destroy the contained value // pre: _Idx == index() if constexpr (_Idx != variant_npos && !is_trivially_destructible_v<_Meta_at_c, _Idx>>) { @@ -862,7 +866,7 @@ public: } } - void _Destroy() noexcept { // destroy the contained value, if any + _CONSTEXPR20 void _Destroy() noexcept { // destroy the contained value, if any if constexpr (!conjunction_v...>) { _Variant_raw_visit(index(), _Storage(), [](auto _Ref) noexcept { if constexpr (decltype(_Ref)::_Idx != variant_npos) { @@ -872,13 +876,13 @@ public: } } - void _Reset() noexcept { // transition to the valueless_by_exception state + _CONSTEXPR20 void _Reset() noexcept { // transition to the valueless_by_exception state _Destroy(); _Set_index(variant_npos); } template - void _Reset() noexcept { + _CONSTEXPR20 void _Reset() noexcept { // transition to the valueless_by_exception state // pre: _Idx == index() if constexpr (_Idx != variant_npos) { @@ -887,25 +891,27 @@ public: } } - void _Construct_from(const _Variant_base& _That) noexcept(conjunction_v...>) { + _CONSTEXPR20 void _Construct_from(const _Variant_base& _That) noexcept( + conjunction_v...>) { // copy _That's contained value into *this // pre: valueless_by_exception() _Variant_raw_visit(_That.index(), _That._Storage(), _Variant_construct_visitor<_Types...>{*this}); } - void _Construct_from(_Variant_base&& _That) noexcept(conjunction_v...>) { + _CONSTEXPR20 void _Construct_from(_Variant_base&& _That) noexcept( + conjunction_v...>) { // move _That's contained value into *this // pre: valueless_by_exception() _Variant_raw_visit(_That.index(), _STD move(_That)._Storage(), _Variant_construct_visitor<_Types...>{*this}); } - void _Assign_from(const _Variant_base& _That) noexcept( + _CONSTEXPR20 void _Assign_from(const _Variant_base& _That) noexcept( conjunction_v..., is_nothrow_copy_assignable<_Types>...>) { // copy assign _That's contained value (if any) into *this _Variant_raw_visit(_That.index(), _That._Storage(), _Variant_assign_visitor<_Types...>{*this}); } - void _Assign_from(_Variant_base&& _That) noexcept( + _CONSTEXPR20 void _Assign_from(_Variant_base&& _That) noexcept( conjunction_v..., is_nothrow_move_assignable<_Types>...>) { // move assign _That's contained value (if any) into *this _Variant_raw_visit(_That.index(), _STD move(_That)._Storage(), _Variant_assign_visitor<_Types...>{*this}); @@ -916,7 +922,7 @@ template struct _Variant_destroy_layer_ : _Variant_base<_Types...> { // destruction behavior facade (non-trivial case) using _Variant_base<_Types...>::_Variant_base; - ~_Variant_destroy_layer_() noexcept { // Destroy contained value, if any + _CONSTEXPR20 ~_Variant_destroy_layer_() noexcept { // Destroy contained value, if any this->_Destroy(); } @@ -1063,7 +1069,8 @@ public: && is_constructible_v<_Variant_init_type<_Ty, _Types...>, _Ty> // && is_assignable_v<_Variant_init_type<_Ty, _Types...>&, _Ty>, // int> = 0> - variant& operator=(_Ty&& _Obj) noexcept(is_nothrow_assignable_v<_Variant_init_type<_Ty, _Types...>&, _Ty>&& + _CONSTEXPR20 variant& operator=(_Ty&& _Obj) noexcept( + is_nothrow_assignable_v<_Variant_init_type<_Ty, _Types...>&, _Ty>&& is_nothrow_constructible_v<_Variant_init_type<_Ty, _Types...>, _Ty>) { // assign/emplace the alternative chosen by overload resolution of _Obj with f(_Types)... constexpr size_t _TargetIdx = _Variant_init_index<_Ty, _Types...>::value; @@ -1089,14 +1096,15 @@ public: template ::value, enable_if_t<_Idx != _Meta_npos && is_constructible_v<_Ty, _ArgTypes...>, int> = 0> - _Ty& emplace(_ArgTypes&&... _Args) noexcept(is_nothrow_constructible_v<_Ty, _ArgTypes...>) /* strengthened */ { + _CONSTEXPR20 _Ty& emplace(_ArgTypes&&... _Args) noexcept( + is_nothrow_constructible_v<_Ty, _ArgTypes...>) /* strengthened */ { // emplace alternative _Ty from _Args... this->_Reset(); return _Emplace_valueless<_Idx>(static_cast<_ArgTypes&&>(_Args)...); } template ::value, enable_if_t<_Idx != _Meta_npos && is_constructible_v<_Ty, initializer_list<_Elem>&, _ArgTypes...>, int> = 0> - _Ty& emplace(initializer_list<_Elem> _Ilist, _ArgTypes&&... _Args) noexcept( + _CONSTEXPR20 _Ty& emplace(initializer_list<_Elem> _Ilist, _ArgTypes&&... _Args) noexcept( is_nothrow_constructible_v<_Ty, initializer_list<_Elem>&, _ArgTypes...>) /* strengthened */ { // emplace alternative _Ty from _Ilist and _Args... this->_Reset(); @@ -1105,7 +1113,7 @@ public: template , _ArgTypes...>, int> = 0> - _Meta_at_c& emplace(_ArgTypes&&... _Args) noexcept( + _CONSTEXPR20 _Meta_at_c& emplace(_ArgTypes&&... _Args) noexcept( is_nothrow_constructible_v<_Meta_at_c, _ArgTypes...>) /* strengthened */ { // emplace alternative _Idx from _Args... this->_Reset(); @@ -1113,7 +1121,7 @@ public: } template , initializer_list<_Elem>&, _ArgTypes...>, int> = 0> - _Meta_at_c& emplace(initializer_list<_Elem> _Ilist, _ArgTypes&&... _Args) noexcept( + _CONSTEXPR20 _Meta_at_c& emplace(initializer_list<_Elem> _Ilist, _ArgTypes&&... _Args) noexcept( is_nothrow_constructible_v<_Meta_at_c, initializer_list<_Elem>&, _ArgTypes...>) /* strengthened */ { // emplace alternative _Idx from _Ilist and _Args... @@ -1128,7 +1136,7 @@ public: #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunused-lambda-capture" #endif // TRANSITION, LLVM-45398 - void swap(variant& _That) noexcept( + _CONSTEXPR20 void swap(variant& _That) noexcept( conjunction_v..., is_nothrow_swappable<_Types>...>) { // exchange the contained values if *this and _That hold the same alternative, otherwise exchange the values of // the variants themselves @@ -1199,17 +1207,16 @@ public: private: template - _Meta_at_c& _Emplace_valueless(_ArgTypes&&... _Args) noexcept( + _CONSTEXPR20 _Meta_at_c& _Emplace_valueless(_ArgTypes&&... _Args) noexcept( is_nothrow_constructible_v<_Meta_at_c, _ArgTypes...>) { // initialize alternative _Idx from _Args... - // pre: valueless_by_exception() - auto& _Obj = _Variant_raw_get<_Idx>(_Storage()); - _Construct_in_place(_Obj, static_cast<_ArgTypes&&>(_Args)...); + _STL_INTERNAL_CHECK(valueless_by_exception()); + _Construct_in_place(_Storage(), integral_constant{}, static_cast<_ArgTypes&&>(_Args)...); this->_Set_index(_Idx); - return _Obj; + return _Variant_raw_get<_Idx>(_Storage()); } - void _Emplace_from(variant&& _That) noexcept(conjunction_v...>) { + _CONSTEXPR20 void _Emplace_from(variant&& _That) noexcept(conjunction_v...>) { // steal the contained value from _That this->_Reset(); _Variant_raw_visit(_That.index(), _That._Storage(), @@ -1710,7 +1717,7 @@ _NODISCARD constexpr bool operator>=(monostate, monostate) noexcept { template ..., is_swappable<_Types>...>, int> = 0> -void swap(variant<_Types...>& _Left, variant<_Types...>& _Right) noexcept(noexcept(_Left.swap(_Right))) { +_CONSTEXPR20 void swap(variant<_Types...>& _Left, variant<_Types...>& _Right) noexcept(noexcept(_Left.swap(_Right))) { _Left.swap(_Right); } diff --git a/stl/inc/xsmf_control.h b/stl/inc/xsmf_control.h index 77bbcda8a16..9c934498add 100644 --- a/stl/inc/xsmf_control.h +++ b/stl/inc/xsmf_control.h @@ -25,7 +25,7 @@ struct _Non_trivial_copy : _Base { // non-trivial copy construction facade using _Base::_Base; _Non_trivial_copy() = default; - _Non_trivial_copy(const _Non_trivial_copy& _That) noexcept( + _CONSTEXPR20 _Non_trivial_copy(const _Non_trivial_copy& _That) noexcept( noexcept(_Base::_Construct_from(static_cast(_That)))) { _Base::_Construct_from(static_cast(_That)); } @@ -47,7 +47,7 @@ struct _Non_trivial_move : _SMF_control_copy<_Base, _Types...> { // non-trivial _Non_trivial_move() = default; _Non_trivial_move(const _Non_trivial_move&) = default; - _Non_trivial_move(_Non_trivial_move&& _That) noexcept( + _CONSTEXPR20 _Non_trivial_move(_Non_trivial_move&& _That) noexcept( noexcept(_Mybase::_Construct_from(static_cast<_Base&&>(_That)))) { _Mybase::_Construct_from(static_cast<_Base&&>(_That)); } @@ -70,7 +70,7 @@ struct _Non_trivial_copy_assign : _SMF_control_move<_Base, _Types...> { // non-t _Non_trivial_copy_assign(const _Non_trivial_copy_assign&) = default; _Non_trivial_copy_assign(_Non_trivial_copy_assign&&) = default; - _Non_trivial_copy_assign& operator=(const _Non_trivial_copy_assign& _That) noexcept( + _CONSTEXPR20 _Non_trivial_copy_assign& operator=(const _Non_trivial_copy_assign& _That) noexcept( noexcept(_Mybase::_Assign_from(static_cast(_That)))) { _Mybase::_Assign_from(static_cast(_That)); return *this; @@ -109,7 +109,7 @@ struct _Non_trivial_move_assign : _SMF_control_copy_assign<_Base, _Types...> { / _Non_trivial_move_assign(_Non_trivial_move_assign&&) = default; _Non_trivial_move_assign& operator=(const _Non_trivial_move_assign&) = default; - _Non_trivial_move_assign& operator=(_Non_trivial_move_assign&& _That) noexcept( + _CONSTEXPR20 _Non_trivial_move_assign& operator=(_Non_trivial_move_assign&& _That) noexcept( noexcept(_Mybase::_Assign_from(static_cast<_Base&&>(_That)))) { _Mybase::_Assign_from(static_cast<_Base&&>(_That)); return *this; diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index a5185ddd62a..531da87699b 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -246,6 +246,7 @@ // P2102R0 Making "Implicit Expression Variations" More Explicit // P2106R0 Range Algorithm Result Types // P2116R0 Removing tuple-Like Protocol Support From Fixed-Extent span +// P2231R1 Completing constexpr In optional And variant // P2259R1 Repairing Input Range Adaptors And counted_iterator // P2325R3 Views Should Not Be Required To Be Default Constructible // P2328R1 join_view Should Join All views Of ranges @@ -1208,7 +1209,6 @@ #define __cpp_lib_memory_resource 201603L #define __cpp_lib_node_extract 201606L #define __cpp_lib_not_fn 201603L -#define __cpp_lib_optional 201606L #ifndef _M_CEE #define __cpp_lib_parallel_algorithm 201603L #endif // _M_CEE @@ -1218,7 +1218,6 @@ #define __cpp_lib_shared_ptr_weak_type 201606L #define __cpp_lib_string_view 201803L #define __cpp_lib_to_chars 201611L -#define __cpp_lib_variant 202102L #endif // _HAS_CXX17 // C++20 @@ -1331,7 +1330,15 @@ #if _HAS_CXX20 #define __cpp_lib_array_constexpr 201811L // P1032R1 Miscellaneous constexpr #elif _HAS_CXX17 // ^^^ _HAS_CXX20 / _HAS_CXX17 vvv -#define __cpp_lib_array_constexpr 201803L +#define __cpp_lib_array_constexpr 201803L // P0858R0 Constexpr Iterator Requirements +#endif // _HAS_CXX17 + +#if _HAS_CXX20 && (defined(__clang__) || defined(__EDG__)) // TRANSITION, DevCom-1331017 +#define __cpp_lib_optional 202106L // P2231R1 Completing constexpr In optional And variant +#define __cpp_lib_variant 202106L // P2231R1 Completing constexpr In optional And variant +#elif _HAS_CXX17 // ^^^ _HAS_CXX20 / _HAS_CXX17 vvv +#define __cpp_lib_optional 201606L // P0307R2 Making Optional Greater Equal Again +#define __cpp_lib_variant 202102L // P2162R2 Inheriting From variant #endif // _HAS_CXX17 #if _HAS_CXX20 && defined(__cpp_lib_concepts) // TRANSITION, GH-395 diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index 39350ca0d9f..71e5ca45b7e 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -57,12 +57,18 @@ std/language.support/support.limits/support.limits.general/locale.version.pass.c std/language.support/support.limits/support.limits.general/ostream.version.pass.cpp FAIL std/language.support/support.limits/support.limits.general/string_view.version.pass.cpp FAIL +# libc++ doesn't yet implement P2231R1, so it expects an old value for `__cpp_lib_optional` +std/language.support/support.limits/support.limits.general/optional.version.pass.cpp:1 FAIL + # test emits warning C4310: cast truncates constant value std/numerics/bit/bitops.rot/rotl.pass.cpp:0 FAIL # libc++ doesn't yet implement P1754R1 or P1964R2, so it expects an old value for `__cpp_lib_concepts` std/language.support/support.limits/support.limits.general/concepts.version.pass.cpp FAIL +# Bogus test believes that optional cannot be a literal type +std/utilities/optional/optional.object/optional.object.dtor/dtor.pass.cpp:0 FAIL + # *** INTERACTIONS WITH CONTEST / C1XX THAT UPSTREAM LIKELY WON'T FIX *** # Tracked by VSO-593630 " Enable libcxx filesystem tests" diff --git a/tests/libcxx/skipped_tests.txt b/tests/libcxx/skipped_tests.txt index 3390cb1e8e9..1c9fc652b88 100644 --- a/tests/libcxx/skipped_tests.txt +++ b/tests/libcxx/skipped_tests.txt @@ -57,12 +57,18 @@ language.support\support.limits\support.limits.general\locale.version.pass.cpp language.support\support.limits\support.limits.general\ostream.version.pass.cpp language.support\support.limits\support.limits.general\string_view.version.pass.cpp +# libc++ doesn't yet implement P2231R1, so it expects an old value for `__cpp_lib_optional` +language.support\support.limits\support.limits.general\optional.version.pass.cpp + # test emits warning C4310: cast truncates constant value numerics\bit\bitops.rot\rotl.pass.cpp # libc++ doesn't yet implement P1754R1 or P1964R2, so it expects an old value for `__cpp_lib_concepts` language.support\support.limits\support.limits.general\concepts.version.pass.cpp +# Bogus test believes that optional cannot be a literal type +utilities\optional\optional.object\optional.object.dtor\dtor.pass.cpp + # *** INTERACTIONS WITH CONTEST / C1XX THAT UPSTREAM LIKELY WON'T FIX *** # Tracked by VSO-593630 " Enable libcxx filesystem tests" diff --git a/tests/std/test.lst b/tests/std/test.lst index 0aa6125ab29..3cac8635eeb 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -432,6 +432,7 @@ tests\P1682R3_to_underlying tests\P1951R1_default_arguments_pair_forward_ctor tests\P2136R3_invoke_r tests\P2162R2_std_visit_for_derived_classes_from_variant +tests\P2231R1_complete_constexpr_optional_variant tests\VSO_0000000_allocator_propagation tests\VSO_0000000_any_calling_conventions tests\VSO_0000000_c_math_functions diff --git a/tests/std/tests/P0088R3_variant/test.cpp b/tests/std/tests/P0088R3_variant/test.cpp index caa0c6c7955..486ed60d865 100644 --- a/tests/std/tests/P0088R3_variant/test.cpp +++ b/tests/std/tests/P0088R3_variant/test.cpp @@ -6444,10 +6444,8 @@ namespace msvc { namespace big_variant { #ifdef __EDG__ constexpr std::size_t big = 20; -#elif defined(__clang__) - constexpr std::size_t big = 256; // Clang supports more, but avoid the test timing out. -#else // C1XX - constexpr std::size_t big = 120; +#else // C1XX and Clang + constexpr std::size_t big = 64; #endif // tune value of "big" to a bit less than the largest variant the front-end can handle constexpr std::size_t n = 16; diff --git a/tests/std/tests/P0220R1_optional/test.cpp b/tests/std/tests/P0220R1_optional/test.cpp index a7bb292e541..72f0928000a 100644 --- a/tests/std/tests/P0220R1_optional/test.cpp +++ b/tests/std/tests/P0220R1_optional/test.cpp @@ -4596,7 +4596,14 @@ int run_test() typedef X T; static_assert(!std::is_trivially_destructible::value, ""); static_assert(!std::is_trivially_destructible>::value, ""); + +#if TEST_STD_VER > 17 && !defined(__clang__) // TRANSITION, LLVM-48286 + // P2231R1 Completing constexpr In optional And variant + static_assert(std::is_literal_type>::value, ""); +#else // ^^^ after P2231R1 / before P2231R1 vvv static_assert(!std::is_literal_type>::value, ""); +#endif // ^^^ before P2231R1 ^^^ + { X x; optional opt{x}; @@ -7414,6 +7421,7 @@ namespace msvc { void run_test() { Test t; + (void) t; } } // namespace vso614907 } // namespace msvc diff --git a/tests/std/tests/P2231R1_complete_constexpr_optional_variant/env.lst b/tests/std/tests/P2231R1_complete_constexpr_optional_variant/env.lst new file mode 100644 index 00000000000..351a8293d9d --- /dev/null +++ b/tests/std/tests/P2231R1_complete_constexpr_optional_variant/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\usual_20_matrix.lst diff --git a/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp b/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp new file mode 100644 index 00000000000..0f948a7ee5d --- /dev/null +++ b/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp @@ -0,0 +1,345 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include +#include +#include + +using namespace std; + +struct With_trivial_destructor { + int _val = 0; + constexpr With_trivial_destructor(const int val) noexcept : _val(val) {} + constexpr With_trivial_destructor(initializer_list vals) noexcept : _val(*vals.begin()) {} + + constexpr bool operator==(const int right) const noexcept { + return _val == right; + } +}; + +struct With_nontrivial_destructor { + int _val = 0; + constexpr With_nontrivial_destructor(const int val) noexcept : _val(val) {} + constexpr With_nontrivial_destructor(initializer_list vals) noexcept : _val(*vals.begin()) {} + constexpr ~With_nontrivial_destructor() {} + + constexpr bool operator==(const int right) const noexcept { + return _val == right; + } +}; + +struct Dummy { + int _val = 0; +}; + +template +constexpr bool test_optional() { + { // empty construction + optional default_constructed; + assert(!default_constructed.has_value()); + + optional nullopt_constructed{nullopt}; + assert(!nullopt_constructed.has_value()); + } + + { // construction from underlying type + const T input{42}; + optional construct_from_type{input}; + assert(construct_from_type.has_value()); + assert(*construct_from_type == 42); + + optional construct_from_type_rvalue{T{42}}; + assert(construct_from_type_rvalue.has_value()); + assert(*construct_from_type_rvalue == 42); + + optional assign_from_type; + assert(!assign_from_type.has_value()); + assign_from_type = input; + assert(assign_from_type.has_value()); + assert(*assign_from_type == 42); + + optional assign_from_type_rvalue; + assert(!assign_from_type_rvalue.has_value()); + assign_from_type_rvalue = T{42}; + assert(assign_from_type_rvalue.has_value()); + assert(*assign_from_type_rvalue == 42); + } + + { // construction from convertible type + const int input{42}; + optional construct_from_convertible_type{input}; + assert(construct_from_convertible_type.has_value()); + assert(*construct_from_convertible_type == 42); + + optional construct_from_convertible_type_rvalue{42}; + assert(construct_from_convertible_type_rvalue.has_value()); + assert(*construct_from_convertible_type_rvalue == 42); + + optional assign_from_convertible_type; + assert(!assign_from_convertible_type.has_value()); + assign_from_convertible_type = input; + assert(assign_from_convertible_type.has_value()); + assert(*assign_from_convertible_type == 42); + + optional assign_from_convertible_type_rvalue; + assert(!assign_from_convertible_type_rvalue.has_value()); + assign_from_convertible_type_rvalue = 42; + assert(assign_from_convertible_type_rvalue.has_value()); + assert(*assign_from_convertible_type_rvalue == 42); + } + + { // construction from optional with same type + optional constructed{42}; + assert(constructed.has_value()); + assert(*constructed == 42); + + optional copy_constructed{constructed}; + assert(copy_constructed.has_value()); + assert(*copy_constructed == 42); + + optional move_constructed{move(constructed)}; + assert(move_constructed.has_value()); + assert(*move_constructed == 42); + +#if !(defined(__clang__) || defined(__EDG__)) // TRANSITION, DevCom-1331017 + if constexpr (!is_same_v) { + if (!is_constant_evaluated()) { +#endif // TRANSITION + optional copy_assigned; + assert(!copy_assigned.has_value()); + copy_assigned = move_constructed; + assert(copy_assigned.has_value()); + assert(*copy_assigned == 42); + + optional move_assigned; + assert(!move_assigned.has_value()); + move_assigned = move(copy_assigned); + assert(move_assigned.has_value()); + assert(*move_assigned == 42); +#if !(defined(__clang__) || defined(__EDG__)) // TRANSITION, DevCom-1331017 + } + } +#endif // TRANSITION, DevCom-1331017 + } + + { // construction from optional with convertible types + optional input{42}; + + optional construct_from_convertible_optional{input}; + assert(construct_from_convertible_optional.has_value()); + assert(*construct_from_convertible_optional == 42); + + optional construct_from_convertible_optional_rvalue{optional{3}}; + assert(construct_from_convertible_optional_rvalue.has_value()); + assert(*construct_from_convertible_optional_rvalue == 3); + + optional assign_from_convertible_optional; + assert(!assign_from_convertible_optional.has_value()); + assign_from_convertible_optional = input; + assert(assign_from_convertible_optional.has_value()); + assert(*assign_from_convertible_optional == 42); + + optional assign_from_convertible_optional_rvalue; + assert(!assign_from_convertible_optional_rvalue.has_value()); + assign_from_convertible_optional_rvalue = optional{3}; + assert(assign_from_convertible_optional_rvalue.has_value()); + assert(*assign_from_convertible_optional_rvalue == 3); + } + + { // emplace + T input{42}; + optional emplace_copy; + assert(!emplace_copy.has_value()); + emplace_copy.emplace(input); + assert(emplace_copy.has_value()); + assert(*emplace_copy == 42); + + optional emplace_move; + assert(!emplace_move.has_value()); + emplace_move.emplace(T{42}); + assert(emplace_move.has_value()); + assert(*emplace_move == 42); + + optional emplace_conversion; + assert(!emplace_conversion.has_value()); + emplace_conversion.emplace(42); + assert(emplace_conversion.has_value()); + assert(*emplace_conversion == 42); + + optional emplace_initializer_list; + assert(!emplace_initializer_list.has_value()); + emplace_initializer_list.emplace({42, 43}); + assert(emplace_initializer_list.has_value()); + assert(*emplace_initializer_list == 42); + } + + { // reset + optional resetted{42}; + resetted.reset(); + assert(!resetted.has_value()); + } + + { // swap + optional left{42}; + optional right{3}; + assert(*left == 42); + assert(*right == 3); + + left.swap(right); + assert(*left == 3); + assert(*right == 42); + + swap(left, right); + assert(*left == 42); + assert(*right == 3); + } + return true; +} + +template +constexpr bool test_variant() { + { // construction from underlying type + const T input{42}; + variant construct_from_type{input}; + assert(construct_from_type.index() == 1); + assert(get(construct_from_type) == 42); + + variant construct_from_type_rvalue{T{42}}; + assert(construct_from_type_rvalue.index() == 1); + assert(get(construct_from_type_rvalue) == 42); + + variant assign_from_type; + assert(assign_from_type.index() == 0); + assign_from_type = input; + assert(assign_from_type.index() == 1); + assert(get(assign_from_type) == 42); + + variant assign_from_type_rvalue; + assert(assign_from_type_rvalue.index() == 0); + assign_from_type_rvalue = T{42}; + assert(assign_from_type_rvalue.index() == 1); + assert(get(assign_from_type_rvalue) == 42); + } + + { // construction from variant with same type + variant constructed{T{42}}; + assert(constructed.index() == 1); + assert(get(constructed) == 42); + + variant copy_constructed{constructed}; + assert(copy_constructed.index() == 1); + assert(get(copy_constructed) == 42); + + variant move_constructed{move(constructed)}; + assert(move_constructed.index() == 1); + assert(get(move_constructed) == 42); + +#if !(defined(__clang__) || defined(__EDG__)) // TRANSITION, DevCom-1331017 + if constexpr (!is_same_v) { + if (!is_constant_evaluated()) { +#endif // TRANSITION + variant copy_assigned; + assert(copy_assigned.index() == 0); + copy_assigned = constructed; + assert(copy_assigned.index() == 1); + assert(get(copy_assigned) == 42); + + variant move_assigned; + assert(move_assigned.index() == 0); + move_assigned = move(constructed); + assert(move_assigned.index() == 1); + assert(get(move_assigned) == 42); +#if !(defined(__clang__) || defined(__EDG__)) // TRANSITION, DevCom-1331017 + } + } +#endif // TRANSITION + } + + { // emplace type + T input{42}; + variant emplace_copy; + assert(emplace_copy.index() == 0); + emplace_copy.template emplace(input); + assert(emplace_copy.index() == 1); + assert(get(emplace_copy) == 42); + + variant emplace_move; + assert(emplace_move.index() == 0); + emplace_move.template emplace(T{42}); + assert(emplace_move.index() == 1); + assert(get(emplace_move) == 42); + + variant emplace_conversion; + assert(emplace_conversion.index() == 0); + emplace_conversion.template emplace(42); + assert(emplace_conversion.index() == 1); + assert(get(emplace_conversion) == 42); + + variant emplace_initializer_list; + assert(emplace_initializer_list.index() == 0); + emplace_initializer_list.template emplace({42, 43}); + assert(emplace_initializer_list.index() == 1); + assert(get(emplace_initializer_list) == 42); + } + + { // emplace index + T input{42}; + variant emplace_copy; + assert(emplace_copy.index() == 0); + emplace_copy.template emplace<1>(input); + assert(emplace_copy.index() == 1); + assert(get(emplace_copy) == 42); + + variant emplace_move; + assert(emplace_move.index() == 0); + emplace_move.template emplace<1>(T{42}); + assert(emplace_move.index() == 1); + assert(get(emplace_move) == 42); + + variant emplace_conversion; + assert(emplace_conversion.index() == 0); + emplace_conversion.template emplace<1>(42); + assert(emplace_conversion.index() == 1); + assert(get(emplace_conversion) == 42); + + variant emplace_initializer_list; + assert(emplace_initializer_list.index() == 0); + emplace_initializer_list.template emplace<1>({42, 43}); + assert(emplace_initializer_list.index() == 1); + assert(get(emplace_initializer_list) == 42); + } + + { // swap + variant left{T{42}}; + variant right; + assert(left.index() == 1); + assert(get(left) == 42); + assert(right.index() == 0); + + left.swap(right); + assert(right.index() == 1); + assert(get(right) == 42); + assert(left.index() == 0); + + swap(left, right); + assert(left.index() == 1); + assert(get(left) == 42); + assert(right.index() == 0); + } + return true; +} + +int main() { + test_optional(); + test_optional(); + static_assert(test_optional()); + static_assert(test_optional()); + + test_variant(); + test_variant(); + static_assert(test_variant()); + static_assert(test_variant()); +} 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 2474c300061..e9f0cf006ca 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 @@ -1208,7 +1208,15 @@ STATIC_ASSERT(__cpp_lib_not_fn == 201603L); STATIC_ASSERT(__cpp_lib_null_iterators == 201304L); #endif -#if _HAS_CXX17 +#if _HAS_CXX20 && (defined(__clang__) || defined(__EDG__)) // TRANSITION, DevCom-1331017 +#ifndef __cpp_lib_optional +#error __cpp_lib_optional is not defined +#elif __cpp_lib_optional != 202106L +#error __cpp_lib_optional is not 202106L +#else +STATIC_ASSERT(__cpp_lib_optional == 202106L); +#endif +#elif _HAS_CXX17 #ifndef __cpp_lib_optional #error __cpp_lib_optional is not defined #elif __cpp_lib_optional != 201606L @@ -1726,7 +1734,15 @@ STATIC_ASSERT(__cpp_lib_unwrap_ref == 201811L); #endif #endif -#if _HAS_CXX17 +#if _HAS_CXX20 && (defined(__clang__) || defined(__EDG__)) // TRANSITION, DevCom-1331017 +#ifndef __cpp_lib_variant +#error __cpp_lib_variant is not defined +#elif __cpp_lib_variant != 202106L +#error __cpp_lib_variant is not 202106L +#else +STATIC_ASSERT(__cpp_lib_variant == 202106L); +#endif +#elif _HAS_CXX17 #ifndef __cpp_lib_variant #error __cpp_lib_variant is not defined #elif __cpp_lib_variant != 202102L