From 74f872b6277fa009377a7009d8079bbf39f3be04 Mon Sep 17 00:00:00 2001 From: Michael Schellenberger Costa Date: Fri, 11 Jun 2021 22:06:26 +0200 Subject: [PATCH 01/38] Implement P2231R1 Completing constexpr In optional --- stl/inc/optional | 44 +++++++++++++++++++++++--------------------- stl/inc/yvals_core.h | 9 ++++++++- 2 files changed, 31 insertions(+), 22 deletions(-) diff --git a/stl/inc/optional b/stl/inc/optional index d54a2f1d56b..9e176ed4da8 100644 --- a/stl/inc/optional +++ b/stl/inc/optional @@ -70,7 +70,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_DYNALLOC void reset() noexcept { _Has_value = false; } }; @@ -83,7 +83,7 @@ struct _Optional_destruct_base<_Ty, false> { // either contains a value of _Ty o }; bool _Has_value; - ~_Optional_destruct_base() noexcept { + _CONSTEXPR20_DYNALLOC ~_Optional_destruct_base() noexcept { if (_Has_value) { _Destroy_in_place(_Value); } @@ -95,12 +95,12 @@ struct _Optional_destruct_base<_Ty, false> { // either contains a value of _Ty o constexpr explicit _Optional_destruct_base(in_place_t, _Types&&... _Args) : _Value(_STD forward<_Types>(_Args)...), _Has_value{true} {} // initialize contained value with _Args... - _Optional_destruct_base(const _Optional_destruct_base&) = default; - _Optional_destruct_base(_Optional_destruct_base&&) = default; - _Optional_destruct_base& operator=(const _Optional_destruct_base&) = default; - _Optional_destruct_base& operator=(_Optional_destruct_base&&) = default; + _CONSTEXPR20_DYNALLOC _Optional_destruct_base(const _Optional_destruct_base&) = default; + _CONSTEXPR20_DYNALLOC _Optional_destruct_base(_Optional_destruct_base&&) = default; + _CONSTEXPR20_DYNALLOC _Optional_destruct_base& operator=(const _Optional_destruct_base&) = default; + _CONSTEXPR20_DYNALLOC _Optional_destruct_base& operator=(_Optional_destruct_base&&) = default; - void reset() noexcept { + _CONSTEXPR20_DYNALLOC void reset() noexcept { if (_Has_value) { _Destroy_in_place(_Value); _Has_value = false; @@ -114,7 +114,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_DYNALLOC _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; @@ -122,7 +123,7 @@ struct _Optional_construct_base : _Optional_destruct_base<_Ty> { } template - void _Assign(_Ty2&& _Right) { // assign / initialize the contained value from _Right + _CONSTEXPR20_DYNALLOC void _Assign(_Ty2&& _Right) { // assign / initialize the contained value from _Right if (this->_Has_value) { this->_Value = _STD forward<_Ty2>(_Right); } else { @@ -131,7 +132,7 @@ struct _Optional_construct_base : _Optional_destruct_base<_Ty> { } template - void _Construct_from(_Self&& _Right) noexcept( + _CONSTEXPR20_DYNALLOC 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) { @@ -140,7 +141,7 @@ struct _Optional_construct_base : _Optional_destruct_base<_Ty> { } template - void _Assign_from(_Self&& _Right) noexcept( + _CONSTEXPR20_DYNALLOC 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 @@ -205,7 +206,7 @@ public: #if _HAS_CONDITIONAL_EXPLICIT template , is_constructible<_Ty, const _Ty2&>>, int> = 0> - explicit(!is_convertible_v) optional(const optional<_Ty2>& _Right) { + _CONSTEXPR20_DYNALLOC explicit(!is_convertible_v) optional(const optional<_Ty2>& _Right) { if (_Right) { this->_Construct(*_Right); } @@ -231,7 +232,7 @@ public: #if _HAS_CONDITIONAL_EXPLICIT template , is_constructible<_Ty, _Ty2>>, int> = 0> - explicit(!is_convertible_v<_Ty2, _Ty>) optional(optional<_Ty2>&& _Right) { + _CONSTEXPR20_DYNALLOC explicit(!is_convertible_v<_Ty2, _Ty>) optional(optional<_Ty2>&& _Right) { if (_Right) { this->_Construct(_STD move(*_Right)); } @@ -256,7 +257,7 @@ public: #endif // ^^^ !_HAS_CONDITIONAL_EXPLICIT ^^^ // assignment [optional.object.assign] - optional& operator=(nullopt_t) noexcept { + _CONSTEXPR20_DYNALLOC optional& operator=(nullopt_t) noexcept { reset(); return *this; } @@ -265,7 +266,7 @@ public: negation, is_same<_Ty, decay_t<_Ty2>>>>, is_constructible<_Ty, _Ty2>, is_assignable<_Ty&, _Ty2>>, int> = 0> - optional& operator=(_Ty2&& _Right) { + _CONSTEXPR20_DYNALLOC optional& operator=(_Ty2&& _Right) { this->_Assign(_STD forward<_Ty2>(_Right)); return *this; } @@ -279,7 +280,7 @@ public: template , is_constructible<_Ty, const _Ty2&>, is_assignable<_Ty&, const _Ty2&>>, int> = 0> - optional& operator=(const optional<_Ty2>& _Right) { + _CONSTEXPR20_DYNALLOC optional& operator=(const optional<_Ty2>& _Right) { if (_Right) { this->_Assign(*_Right); } else { @@ -292,7 +293,7 @@ public: template , is_constructible<_Ty, _Ty2>, is_assignable<_Ty&, _Ty2>>, int> = 0> - optional& operator=(optional<_Ty2>&& _Right) { + _CONSTEXPR20_DYNALLOC optional& operator=(optional<_Ty2>&& _Right) { if (_Right) { this->_Assign(_STD move(*_Right)); } else { @@ -303,20 +304,21 @@ public: } template - _Ty& emplace(_Types&&... _Args) { + _CONSTEXPR20_DYNALLOC _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_DYNALLOC _Ty& emplace(initializer_list<_Elem> _Ilist, _Types&&... _Args) { reset(); return this->_Construct(_Ilist, _STD forward<_Types>(_Args)...); } // swap [optional.object.swap] - void swap(optional& _Right) noexcept(is_nothrow_move_constructible_v<_Ty>&& is_nothrow_swappable_v<_Ty>) { + _CONSTEXPR20_DYNALLOC 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>, @@ -659,7 +661,7 @@ _NODISCARD constexpr compare_three_way_result_t<_Ty1, _Ty2> // FUNCTION TEMPLATE swap [optional.specalg] template && is_swappable_v<_Ty>, int> = 0> -void swap(optional<_Ty>& _Left, optional<_Ty>& _Right) noexcept(noexcept(_Left.swap(_Right))) { +_CONSTEXPR20_DYNALLOC void swap(optional<_Ty>& _Left, optional<_Ty>& _Right) noexcept(noexcept(_Left.swap(_Right))) { _Left.swap(_Right); } diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index 66a66b4464a..ccbf8889c32 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -245,6 +245,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 // P????R? directory_entry::clear_cache() // _HAS_CXX20 indirectly controls: @@ -1182,7 +1183,13 @@ #define __cpp_lib_memory_resource 201603L #define __cpp_lib_node_extract 201606L #define __cpp_lib_not_fn 201603L -#define __cpp_lib_optional 201606L + +#if _HAS_CXX20 && defined(__cpp_constexpr_dynamic_alloc) +#define __cpp_lib_optional 202106L +#else +#define __cpp_lib_optional 201606L +#endif // __cpp_constexpr_dynamic_alloc + #ifndef _M_CEE #define __cpp_lib_parallel_algorithm 201603L #endif // _M_CEE From f9e4e18bea1a78a63853ac7c259ed2970f02ef42 Mon Sep 17 00:00:00 2001 From: Michael Schellenberger Costa Date: Sat, 12 Jun 2021 11:10:58 +0200 Subject: [PATCH 02/38] Implement P2231R1 Completing constexpr in variant Addresses #1982 --- stl/inc/variant | 107 ++++++++++++++++++++++++------------------- stl/inc/yvals_core.h | 7 ++- 2 files changed, 65 insertions(+), 49 deletions(-) diff --git a/stl/inc/variant b/stl/inc/variant index 6c53432cade..c8a93a1c267 100644 --- a/stl/inc/variant +++ b/stl/inc/variant @@ -457,7 +457,7 @@ public: _Variant_storage<_Rest...> _Tail; }; - _Variant_storage_() noexcept {} // no initialization (no active member) + _CONSTEXPR20_DYNALLOC _Variant_storage_() noexcept {} // no initialization (no active member) template constexpr explicit _Variant_storage_(integral_constant, _Types&&... _Args) noexcept( @@ -492,11 +492,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_DYNALLOC ~_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_DYNALLOC _Variant_storage_() noexcept {} // no initialization (no active member) template constexpr explicit _Variant_storage_(integral_constant, _Types&&... _Args) noexcept( @@ -508,10 +509,10 @@ public: is_nothrow_constructible_v<_Variant_storage<_Rest...>, integral_constant, _Types...>) : _Tail(integral_constant{}, static_cast<_Types&&>(_Args)...) {} // initialize _Tail (recurse) - _Variant_storage_(_Variant_storage_&&) = default; - _Variant_storage_(const _Variant_storage_&) = default; - _Variant_storage_& operator=(_Variant_storage_&&) = default; - _Variant_storage_& operator=(const _Variant_storage_&) = default; + _CONSTEXPR20_DYNALLOC _Variant_storage_(_Variant_storage_&&) = default; + _CONSTEXPR20_DYNALLOC _Variant_storage_(const _Variant_storage_&) = default; + _CONSTEXPR20_DYNALLOC _Variant_storage_& operator=(_Variant_storage_&&) = default; + _CONSTEXPR20_DYNALLOC _Variant_storage_& operator=(const _Variant_storage_&) = default; _NODISCARD constexpr _First& _Get() & noexcept { return _Head; @@ -548,11 +549,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_DYNALLOC ~_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_DYNALLOC _Variant_storage_() noexcept {} // no initialization (no active member) template constexpr explicit _Variant_storage_(integral_constant, _Types&&... _Args) noexcept( @@ -564,10 +566,10 @@ public: is_nothrow_constructible_v<_Variant_storage<_Rest...>, integral_constant, _Types...>) : _Tail(integral_constant{}, static_cast<_Types&&>(_Args)...) {} // initialize _Tail (recurse) - _Variant_storage_(_Variant_storage_&&) = default; - _Variant_storage_(const _Variant_storage_&) = default; - _Variant_storage_& operator=(_Variant_storage_&&) = default; - _Variant_storage_& operator=(const _Variant_storage_&) = default; + _CONSTEXPR20_DYNALLOC _Variant_storage_(_Variant_storage_&&) = default; + _CONSTEXPR20_DYNALLOC _Variant_storage_(const _Variant_storage_&) = default; + _CONSTEXPR20_DYNALLOC _Variant_storage_& operator=(_Variant_storage_&&) = default; + _CONSTEXPR20_DYNALLOC _Variant_storage_& operator=(const _Variant_storage_&) = default; _NODISCARD constexpr _First ^ &_Get() & noexcept { return _Head._Item; @@ -779,9 +781,10 @@ 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_DYNALLOC 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() (void) _Source; // TRANSITION, DevCom-1004719 if constexpr (_Idx != variant_npos) { auto& _Target = _Variant_raw_get<_Idx>(_Self._Storage()); @@ -800,9 +803,10 @@ 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_DYNALLOC 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 @@ -855,7 +859,8 @@ public: return _STD move(*this); } - _Variant_base() noexcept : _Storage_t{}, _Which{_Invalid_index} {} // initialize to the value-less state + _CONSTEXPR20_DYNALLOC _Variant_base() noexcept + : _Storage_t{}, _Which{_Invalid_index} {} // initialize to the value-less state template , _Idx>, _UTypes...>, int> = 0> @@ -872,14 +877,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_DYNALLOC 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_DYNALLOC void _Destroy() noexcept { // destroy the contained value // pre: _Idx == index() if constexpr (_Idx != variant_npos && !is_trivially_destructible_v<_Meta_at_c, _Idx>>) { @@ -887,7 +892,7 @@ public: } } - void _Destroy() noexcept { // destroy the contained value, if any + _CONSTEXPR20_DYNALLOC 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) { @@ -897,13 +902,13 @@ public: } } - void _Reset() noexcept { // transition to the valueless_by_exception state + _CONSTEXPR20_DYNALLOC void _Reset() noexcept { // transition to the valueless_by_exception state _Destroy(); _Set_index(variant_npos); } template - void _Reset() noexcept { + _CONSTEXPR20_DYNALLOC void _Reset() noexcept { // transition to the valueless_by_exception state // pre: _Idx == index() if constexpr (_Idx != variant_npos) { @@ -912,25 +917,27 @@ public: } } - void _Construct_from(const _Variant_base& _That) noexcept(conjunction_v...>) { + _CONSTEXPR20_DYNALLOC 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_DYNALLOC 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_DYNALLOC 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_DYNALLOC 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}); @@ -941,15 +948,15 @@ 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_DYNALLOC ~_Variant_destroy_layer_() noexcept { // Destroy contained value, if any this->_Destroy(); } - _Variant_destroy_layer_() = default; - _Variant_destroy_layer_(const _Variant_destroy_layer_&) = default; - _Variant_destroy_layer_(_Variant_destroy_layer_&&) = default; - _Variant_destroy_layer_& operator=(const _Variant_destroy_layer_&) = default; - _Variant_destroy_layer_& operator=(_Variant_destroy_layer_&&) = default; + _CONSTEXPR20_DYNALLOC _Variant_destroy_layer_() = default; + _CONSTEXPR20_DYNALLOC _Variant_destroy_layer_(const _Variant_destroy_layer_&) = default; + _CONSTEXPR20_DYNALLOC _Variant_destroy_layer_(_Variant_destroy_layer_&&) = default; + _CONSTEXPR20_DYNALLOC _Variant_destroy_layer_& operator=(const _Variant_destroy_layer_&) = default; + _CONSTEXPR20_DYNALLOC _Variant_destroy_layer_& operator=(_Variant_destroy_layer_&&) = default; }; template @@ -1091,7 +1098,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_DYNALLOC 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; @@ -1118,14 +1126,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_DYNALLOC _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_DYNALLOC _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(); @@ -1134,7 +1143,7 @@ public: template , _ArgTypes...>, int> = 0> - _Meta_at_c& emplace(_ArgTypes&&... _Args) noexcept( + _CONSTEXPR20_DYNALLOC _Meta_at_c& emplace(_ArgTypes&&... _Args) noexcept( is_nothrow_constructible_v<_Meta_at_c, _ArgTypes...>) /* strengthened */ { // emplace alternative _Idx from _Args... this->_Reset(); @@ -1142,9 +1151,9 @@ public: } template , initializer_list<_Elem>&, _ArgTypes...>, int> = 0> - _Meta_at_c& emplace(initializer_list<_Elem> _Ilist, _ArgTypes&&... _Args) noexcept( - is_nothrow_constructible_v<_Meta_at_c, initializer_list<_Elem>&, - _ArgTypes...>) /* strengthened */ { + _CONSTEXPR20_DYNALLOC _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... this->_Reset(); return _Emplace_valueless<_Idx>(_Ilist, static_cast<_ArgTypes&&>(_Args)...); @@ -1159,7 +1168,7 @@ public: #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunused-lambda-capture" #endif // TRANSITION, LLVM-45398 - void swap(variant& _That) noexcept( + _CONSTEXPR20_DYNALLOC 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 @@ -1230,7 +1239,7 @@ public: private: template - _Meta_at_c& _Emplace_valueless(_ArgTypes&&... _Args) noexcept( + _CONSTEXPR20_DYNALLOC _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() @@ -1240,7 +1249,8 @@ private: return _Obj; } - void _Emplace_from(variant&& _That) noexcept(conjunction_v...>) { + _CONSTEXPR20_DYNALLOC void _Emplace_from(variant&& _That) noexcept( + conjunction_v...>) { // steal the contained value from _That this->_Reset(); _Variant_raw_visit(_That.index(), _That._Storage(), @@ -1746,7 +1756,8 @@ _NODISCARD constexpr bool operator>=(monostate, monostate) noexcept { // SPECIALIZED ALGORITHMS [variant.specalg] template ..., is_swappable<_Types>...>, int> = 0> -void swap(variant<_Types...>& _Left, variant<_Types...>& _Right) noexcept(noexcept(_Left.swap(_Right))) { +_CONSTEXPR20_DYNALLOC void swap(variant<_Types...>& _Left, variant<_Types...>& _Right) noexcept( + noexcept(_Left.swap(_Right))) { _Left.swap(_Right); } diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index ccbf8889c32..699402d9a2e 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -1199,7 +1199,12 @@ #define __cpp_lib_shared_ptr_weak_type 201606L #define __cpp_lib_string_view 201803L #define __cpp_lib_to_chars 201611L -#define __cpp_lib_variant 201606L + +#if _HAS_CXX20 && defined(__cpp_constexpr_dynamic_alloc) +#define __cpp_lib_variant 202106L +#else +#define __cpp_lib_variant 201606L +#endif // __cpp_constexpr_dynamic_alloc #endif // _HAS_CXX17 // C++20 From f77c5aa993dcffc01285ca993b6faf4391ac37e8 Mon Sep 17 00:00:00 2001 From: Michael Schellenberger Costa Date: Sat, 12 Jun 2021 20:44:55 +0200 Subject: [PATCH 03/38] Properly test the feature test macros --- .../test.compile.pass.cpp | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) 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 0da859a6bf9..a10d5cbeebb 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 @@ -1171,7 +1171,15 @@ STATIC_ASSERT(__cpp_lib_not_fn == 201603L); STATIC_ASSERT(__cpp_lib_null_iterators == 201304L); #endif -#if _HAS_CXX17 +#if _HAS_CXX20 +#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 @@ -1633,7 +1641,15 @@ STATIC_ASSERT(__cpp_lib_unwrap_ref == 201811L); #endif #endif -#if _HAS_CXX17 +#if _HAS_CXX20 +#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 != 201606L From 0c36ad90c993957e7b79c35de9e004cfc5fbedee Mon Sep 17 00:00:00 2001 From: Michael Schellenberger Costa Date: Thu, 24 Jun 2021 20:47:21 +0200 Subject: [PATCH 04/38] Address review comments Co-authored-by: Casey Carter --- stl/inc/optional | 12 +++---- stl/inc/variant | 34 +++++++++---------- stl/inc/xsmf_control.h | 8 ++--- stl/inc/yvals_core.h | 12 +++---- .../test.compile.pass.cpp | 4 +-- 5 files changed, 35 insertions(+), 35 deletions(-) diff --git a/stl/inc/optional b/stl/inc/optional index 9e176ed4da8..d5eae9afd62 100644 --- a/stl/inc/optional +++ b/stl/inc/optional @@ -95,10 +95,10 @@ struct _Optional_destruct_base<_Ty, false> { // either contains a value of _Ty o constexpr explicit _Optional_destruct_base(in_place_t, _Types&&... _Args) : _Value(_STD forward<_Types>(_Args)...), _Has_value{true} {} // initialize contained value with _Args... - _CONSTEXPR20_DYNALLOC _Optional_destruct_base(const _Optional_destruct_base&) = default; - _CONSTEXPR20_DYNALLOC _Optional_destruct_base(_Optional_destruct_base&&) = default; - _CONSTEXPR20_DYNALLOC _Optional_destruct_base& operator=(const _Optional_destruct_base&) = default; - _CONSTEXPR20_DYNALLOC _Optional_destruct_base& operator=(_Optional_destruct_base&&) = default; + _Optional_destruct_base(const _Optional_destruct_base&) = default; + _Optional_destruct_base(_Optional_destruct_base&&) = default; + _Optional_destruct_base& operator=(const _Optional_destruct_base&) = default; + _Optional_destruct_base& operator=(_Optional_destruct_base&&) = default; _CONSTEXPR20_DYNALLOC void reset() noexcept { if (_Has_value) { @@ -114,8 +114,8 @@ struct _Optional_construct_base : _Optional_destruct_base<_Ty> { using _Optional_destruct_base<_Ty>::_Optional_destruct_base; template - _CONSTEXPR20_DYNALLOC _Ty& _Construct( - _Types&&... _Args) { // transition from the empty to the value-containing state + _CONSTEXPR20_DYNALLOC _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; diff --git a/stl/inc/variant b/stl/inc/variant index c8a93a1c267..2b7d353b398 100644 --- a/stl/inc/variant +++ b/stl/inc/variant @@ -509,10 +509,10 @@ public: is_nothrow_constructible_v<_Variant_storage<_Rest...>, integral_constant, _Types...>) : _Tail(integral_constant{}, static_cast<_Types&&>(_Args)...) {} // initialize _Tail (recurse) - _CONSTEXPR20_DYNALLOC _Variant_storage_(_Variant_storage_&&) = default; - _CONSTEXPR20_DYNALLOC _Variant_storage_(const _Variant_storage_&) = default; - _CONSTEXPR20_DYNALLOC _Variant_storage_& operator=(_Variant_storage_&&) = default; - _CONSTEXPR20_DYNALLOC _Variant_storage_& operator=(const _Variant_storage_&) = default; + _Variant_storage_(_Variant_storage_&&) = default; + _Variant_storage_(const _Variant_storage_&) = default; + _Variant_storage_& operator=(_Variant_storage_&&) = default; + _Variant_storage_& operator=(const _Variant_storage_&) = default; _NODISCARD constexpr _First& _Get() & noexcept { return _Head; @@ -566,10 +566,10 @@ public: is_nothrow_constructible_v<_Variant_storage<_Rest...>, integral_constant, _Types...>) : _Tail(integral_constant{}, static_cast<_Types&&>(_Args)...) {} // initialize _Tail (recurse) - _CONSTEXPR20_DYNALLOC _Variant_storage_(_Variant_storage_&&) = default; - _CONSTEXPR20_DYNALLOC _Variant_storage_(const _Variant_storage_&) = default; - _CONSTEXPR20_DYNALLOC _Variant_storage_& operator=(_Variant_storage_&&) = default; - _CONSTEXPR20_DYNALLOC _Variant_storage_& operator=(const _Variant_storage_&) = default; + _Variant_storage_(_Variant_storage_&&) = default; + _Variant_storage_(const _Variant_storage_&) = default; + _Variant_storage_& operator=(_Variant_storage_&&) = default; + _Variant_storage_& operator=(const _Variant_storage_&) = default; _NODISCARD constexpr _First ^ &_Get() & noexcept { return _Head._Item; @@ -781,10 +781,10 @@ struct _Variant_construct_visitor { // visitor that constructs the same alternat _Variant_base<_Types...>& _Self; template - _CONSTEXPR20_DYNALLOC 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_DYNALLOC 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()); @@ -952,11 +952,11 @@ struct _Variant_destroy_layer_ : _Variant_base<_Types...> { // destruction behav this->_Destroy(); } - _CONSTEXPR20_DYNALLOC _Variant_destroy_layer_() = default; - _CONSTEXPR20_DYNALLOC _Variant_destroy_layer_(const _Variant_destroy_layer_&) = default; - _CONSTEXPR20_DYNALLOC _Variant_destroy_layer_(_Variant_destroy_layer_&&) = default; - _CONSTEXPR20_DYNALLOC _Variant_destroy_layer_& operator=(const _Variant_destroy_layer_&) = default; - _CONSTEXPR20_DYNALLOC _Variant_destroy_layer_& operator=(_Variant_destroy_layer_&&) = default; + _Variant_destroy_layer_() = default; + _Variant_destroy_layer_(const _Variant_destroy_layer_&) = default; + _Variant_destroy_layer_(_Variant_destroy_layer_&&) = default; + _Variant_destroy_layer_& operator=(const _Variant_destroy_layer_&) = default; + _Variant_destroy_layer_& operator=(_Variant_destroy_layer_&&) = default; }; template diff --git a/stl/inc/xsmf_control.h b/stl/inc/xsmf_control.h index 7013b398ac1..179db0f6fa9 100644 --- a/stl/inc/xsmf_control.h +++ b/stl/inc/xsmf_control.h @@ -26,7 +26,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_DYNALLOC _Non_trivial_copy(const _Non_trivial_copy& _That) noexcept( noexcept(_Base::_Construct_from(static_cast(_That)))) { _Base::_Construct_from(static_cast(_That)); } @@ -49,7 +49,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_DYNALLOC _Non_trivial_move(_Non_trivial_move&& _That) noexcept( noexcept(_Mybase::_Construct_from(static_cast<_Base&&>(_That)))) { _Mybase::_Construct_from(static_cast<_Base&&>(_That)); } @@ -73,7 +73,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_DYNALLOC _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; @@ -113,7 +113,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_DYNALLOC _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 699402d9a2e..c96229e10f5 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -1184,11 +1184,11 @@ #define __cpp_lib_node_extract 201606L #define __cpp_lib_not_fn 201603L -#if _HAS_CXX20 && defined(__cpp_constexpr_dynamic_alloc) +#if _HAS_CXX20 && defined(__cpp_constexpr_dynamic_alloc) // == __cpp_lib_constexpr_dynamic_alloc #define __cpp_lib_optional 202106L -#else +#else // ^^^ __cpp_lib_constexpr_dynamic_alloc ^^^ / vvv !__cpp_lib_constexpr_dynamic_alloc vvv #define __cpp_lib_optional 201606L -#endif // __cpp_constexpr_dynamic_alloc +#endif // !__cpp_lib_constexpr_dynamic_alloc #ifndef _M_CEE #define __cpp_lib_parallel_algorithm 201603L @@ -1200,11 +1200,11 @@ #define __cpp_lib_string_view 201803L #define __cpp_lib_to_chars 201611L -#if _HAS_CXX20 && defined(__cpp_constexpr_dynamic_alloc) +#if _HAS_CXX20 && defined(__cpp_constexpr_dynamic_alloc) // == __cpp_lib_constexpr_dynamic_alloc #define __cpp_lib_variant 202106L -#else +#else // ^^^ __cpp_lib_constexpr_dynamic_alloc ^^^ / vvv !__cpp_lib_constexpr_dynamic_alloc vvv #define __cpp_lib_variant 201606L -#endif // __cpp_constexpr_dynamic_alloc +#endif // !__cpp_lib_constexpr_dynamic_alloc #endif // _HAS_CXX17 // C++20 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 a10d5cbeebb..6e634eed142 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 @@ -1171,7 +1171,7 @@ STATIC_ASSERT(__cpp_lib_not_fn == 201603L); STATIC_ASSERT(__cpp_lib_null_iterators == 201304L); #endif -#if _HAS_CXX20 +#ifdef __cpp_lib_constexpr_dynamic_alloc #ifndef __cpp_lib_optional #error __cpp_lib_optional is not defined #elif __cpp_lib_optional != 202106L @@ -1641,7 +1641,7 @@ STATIC_ASSERT(__cpp_lib_unwrap_ref == 201811L); #endif #endif -#if _HAS_CXX20 +#ifdef __cpp_constexpr_dynamic_alloc #ifndef __cpp_lib_variant #error __cpp_lib_variant is not defined #elif __cpp_lib_variant != 202106L From ca409083f1240be6af0d2245253f57a4edd68063 Mon Sep 17 00:00:00 2001 From: Michael Schellenberger Costa Date: Thu, 24 Jun 2021 21:08:24 +0200 Subject: [PATCH 05/38] Make the test pass --- tests/libcxx/expected_results.txt | 6 ++++++ tests/libcxx/skipped_tests.txt | 6 ++++++ tests/std/tests/P0220R1_optional/test.cpp | 5 +++++ 3 files changed, 17 insertions(+) diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index dedf6abf6c6..24ea4093d3e 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -57,6 +57,12 @@ 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` and `__cpp_lib_variant` +# and fails the destructor tests for both +std/language.support/support.limits/support.limits.general/optional.version.pass.cpp +std/language.support/support.limits/support.limits.general/variant.version.pass.cpp +std/utilities/optional/optional.object/optional.object.dtor/dtor.pass.cpp + # test emits warning C4310: cast truncates constant value std/numerics/bit/bitops.rot/rotl.pass.cpp:0 FAIL diff --git a/tests/libcxx/skipped_tests.txt b/tests/libcxx/skipped_tests.txt index 01c1397b584..2e6fa2ec8f9 100644 --- a/tests/libcxx/skipped_tests.txt +++ b/tests/libcxx/skipped_tests.txt @@ -57,6 +57,12 @@ 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` and `__cpp_lib_variant` +# and fails the destructor tests for both +language.support\support.limits\support.limits.general\optional.version.pass.cpp +language.support\support.limits\support.limits.general\variant.version.pass.cpp +utilities\optional\optional.object\optional.object.dtor\dtor.pass.cpp + # test emits warning C4310: cast truncates constant value numerics\bit\bitops.rot\rotl.pass.cpp diff --git a/tests/std/tests/P0220R1_optional/test.cpp b/tests/std/tests/P0220R1_optional/test.cpp index a7bb292e541..f25212ff432 100644 --- a/tests/std/tests/P0220R1_optional/test.cpp +++ b/tests/std/tests/P0220R1_optional/test.cpp @@ -4596,7 +4596,11 @@ int run_test() typedef X T; static_assert(!std::is_trivially_destructible::value, ""); static_assert(!std::is_trivially_destructible>::value, ""); + #ifdef __cpp_lib_constexpr_dynamic_alloc + static_assert(std::is_literal_type>::value, ""); + #else // ^^^ __cpp_lib_constexpr_dynamic_alloc ^^^ / vvv !__cpp_lib_constexpr_dynamic_alloc vvv static_assert(!std::is_literal_type>::value, ""); + #endif // !__cpp_lib_constexpr_dynamic_alloc { X x; optional opt{x}; @@ -7414,6 +7418,7 @@ namespace msvc { void run_test() { Test t; + (void) t; } } // namespace vso614907 } // namespace msvc From 09eff91c13f31ce4367c8e179c6694408e6bd03e Mon Sep 17 00:00:00 2001 From: Michael Schellenberger Costa Date: Thu, 24 Jun 2021 21:09:06 +0200 Subject: [PATCH 06/38] Fix typo --- .../tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 6e634eed142..646302c1516 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 @@ -1641,7 +1641,7 @@ STATIC_ASSERT(__cpp_lib_unwrap_ref == 201811L); #endif #endif -#ifdef __cpp_constexpr_dynamic_alloc +#ifdef __cpp_lib_constexpr_dynamic_alloc #ifndef __cpp_lib_variant #error __cpp_lib_variant is not defined #elif __cpp_lib_variant != 202106L From 23d7fc1033ff4485a539ce9706e8b7d2183dea46 Mon Sep 17 00:00:00 2001 From: Michael Schellenberger Costa Date: Thu, 24 Jun 2021 21:19:55 +0200 Subject: [PATCH 07/38] FAIL --- tests/libcxx/expected_results.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index 24ea4093d3e..b603b8e0a6d 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -59,9 +59,9 @@ std/language.support/support.limits/support.limits.general/string_view.version.p # libc++ doesn't yet implement P2231R1, so it expects an old value for `__cpp_lib_optional` and `__cpp_lib_variant` # and fails the destructor tests for both -std/language.support/support.limits/support.limits.general/optional.version.pass.cpp -std/language.support/support.limits/support.limits.general/variant.version.pass.cpp -std/utilities/optional/optional.object/optional.object.dtor/dtor.pass.cpp +std/language.support/support.limits/support.limits.general/optional.version.pass.cpp FAIL +std/language.support/support.limits/support.limits.general/variant.version.pass.cpp FAIL +std/utilities/optional/optional.object/optional.object.dtor/dtor.pass.cpp FAIL # test emits warning C4310: cast truncates constant value std/numerics/bit/bitops.rot/rotl.pass.cpp:0 FAIL From 6ff6d9a01c8bbe814ae3d8a89b33ae5fe28c5803 Mon Sep 17 00:00:00 2001 From: Michael Schellenberger Costa Date: Thu, 24 Jun 2021 22:26:37 +0200 Subject: [PATCH 08/38] Add some optional tests --- tests/std/test.lst | 1 + .../env.lst | 4 + .../test.cpp | 177 ++++++++++++++++++ 3 files changed, 182 insertions(+) create mode 100644 tests/std/tests/P2231R1_complete_constexpr_optional_variant/env.lst create mode 100644 tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp diff --git a/tests/std/test.lst b/tests/std/test.lst index cba3615d387..7a068a585f4 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -419,6 +419,7 @@ tests\P1423R3_char8_t_remediation tests\P1502R1_standard_library_header_units tests\P1614R2_spaceship tests\P1645R1_constexpr_numeric +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/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..d09f0db4096 --- /dev/null +++ b/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp @@ -0,0 +1,177 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include +#include + +using namespace std; + +struct With_trivial_destrutor { + int _val = 0; + constexpr With_trivial_destrutor(const int val) noexcept : _val(val) {} + constexpr With_trivial_destrutor(initializer_list vals) noexcept : _val(*vals.begin()) {} + + constexpr bool operator==(const int right) const noexcept { + return _val == right; + } +}; + +struct With_nontrivial_destrutor { + int _val = 0; + constexpr With_nontrivial_destrutor(const int val) noexcept : _val(val) {} + constexpr With_nontrivial_destrutor(initializer_list vals) noexcept : _val(*vals.begin()) {} + constexpr ~With_nontrivial_destrutor() {} + + constexpr bool operator==(const int right) const noexcept { + return _val == right; + } +}; + +template +_CONSTEXPR20_DYNALLOC bool test_optional() { + { // construction from underlying type + const T input{42}; + optional copy_constructed{input}; + assert(copy_constructed.has_value()); + assert(*copy_constructed == 42); + + optional move_constructed{T{42}}; + assert(move_constructed.has_value()); + assert(*move_constructed == 42); + + optional copy_assigned; + assert(!copy_assigned.has_value()); + copy_assigned = input; + assert(copy_assigned.has_value()); + assert(*copy_assigned == 42); + + optional move_assigned; + assert(!move_assigned.has_value()); + move_assigned = T{42}; + assert(move_assigned.has_value()); + assert(*move_assigned == 42); + } + + { // construction from convertible type + const int input{42}; + optional copy_constructed{input}; + assert(copy_constructed.has_value()); + assert(*copy_constructed == 42); + + optional move_constructed{42}; + assert(move_constructed.has_value()); + assert(*move_constructed == 42); + + optional copy_assigned; + assert(!copy_assigned.has_value()); + copy_assigned = input; + assert(copy_assigned.has_value()); + assert(*copy_assigned == 42); + + optional move_assigned; + assert(!move_assigned.has_value()); + move_assigned = 42; + assert(move_assigned.has_value()); + assert(*move_assigned == 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); + + optional copy_assigned; + assert(!copy_assigned.has_value()); + copy_assigned = constructed; + assert(copy_assigned.has_value()); + assert(*copy_assigned == 42); + + optional move_assigned; + assert(!move_assigned.has_value()); + move_assigned = move(constructed); + assert(move_assigned.has_value()); + assert(*move_assigned == 42); + } + + { // construction from optional with convertible types + optional constructed{42}; + optional input{42}; + + constructed = input; + assert(constructed.has_value()); + assert(*constructed == 42); + + constructed = optional{3}; + assert(constructed.has_value()); + assert(*constructed == 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; +} + +int main() { + test_optional(); + test_optional(); +#ifdef __cpp_lib_constexpr_dynamic_alloc + static_assert(test_optional()); + static_assert(test_optional()); +#endif // __cpp_lib_constexpr_dynamic_alloc +} From 5a956d7477ae7cd89548e94879409d6476e673a5 Mon Sep 17 00:00:00 2001 From: Michael Schellenberger Costa Date: Fri, 25 Jun 2021 10:22:29 +0200 Subject: [PATCH 09/38] Add nullopt tests --- .../P2231R1_complete_constexpr_optional_variant/test.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp b/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp index d09f0db4096..5439d7165ef 100644 --- a/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp +++ b/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp @@ -32,6 +32,14 @@ struct With_nontrivial_destrutor { template _CONSTEXPR20_DYNALLOC bool test_optional() { + { // empty construction + optional defaut_constructed; + assert(!defaut_constructed.has_value()); + + optional nullopt_constructed{nullopt}; + assert(!nullopt_constructed.has_value()); + } + { // construction from underlying type const T input{42}; optional copy_constructed{input}; From 20bdbff1325cb293ea32dbf0f725d94c92521373 Mon Sep 17 00:00:00 2001 From: Michael Schellenberger Costa Date: Fri, 25 Jun 2021 11:08:05 +0200 Subject: [PATCH 10/38] Add variant tests --- .../test.cpp | 107 ++++++++++++++++++ 1 file changed, 107 insertions(+) diff --git a/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp b/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp index 5439d7165ef..8f37cea2b87 100644 --- a/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp +++ b/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp @@ -30,6 +30,8 @@ struct With_nontrivial_destrutor { } }; +struct Dummy {}; + template _CONSTEXPR20_DYNALLOC bool test_optional() { { // empty construction @@ -175,6 +177,104 @@ _CONSTEXPR20_DYNALLOC bool test_optional() { return true; } +template +_CONSTEXPR20_DYNALLOC bool test_variant() { + { // construction from underlying type + const T input{42}; + variant copy_constructed{input}; + assert(copy_constructed.index() == 1); + assert(get(copy_constructed) == 42); + + variant move_constructed{T{42}}; + assert(move_constructed.index() == 1); + assert(get(move_constructed) == 42); + + variant copy_assigned; + assert(copy_assigned.index() == 0); + copy_assigned = input; + assert(copy_assigned.index() == 1); + assert(get(copy_assigned) == 42); + + variant move_assigned; + assert(move_assigned.index() == 0); + move_assigned = T{42}; + assert(move_assigned.index() == 1); + assert(get(move_assigned) == 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); + + 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); + } + + { // emplace + T input{42}; + variant emplace_copy; + assert(emplace_copy.index() == 0); + emplace_copy.emplace<1>(input); + assert(emplace_copy.index() == 1); + assert(get(emplace_copy) == 42); + + variant emplace_move; + assert(emplace_move.index() == 0); + emplace_move.emplace<1>(T{42}); + assert(emplace_move.index() == 1); + assert(get(emplace_move) == 42); + + variant emplace_conversion; + assert(emplace_conversion.index() == 0); + emplace_conversion.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.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(); @@ -182,4 +282,11 @@ int main() { static_assert(test_optional()); static_assert(test_optional()); #endif // __cpp_lib_constexpr_dynamic_alloc + + test_variant(); + test_variant(); +#ifdef __cpp_lib_constexpr_dynamic_alloc + static_assert(test_variant()); + static_assert(test_variant()); +#endif // __cpp_lib_constexpr_dynamic_alloc } From d5cd6f5337b179ea5e679b765e2b831dec637d08 Mon Sep 17 00:00:00 2001 From: Michael Schellenberger Costa Date: Fri, 25 Jun 2021 11:35:58 +0200 Subject: [PATCH 11/38] Avoid UB in variant::_Emplace_valueless --- stl/inc/variant | 24 +++++++------- .../test.cpp | 31 ++++++++++++++++++- 2 files changed, 41 insertions(+), 14 deletions(-) diff --git a/stl/inc/variant b/stl/inc/variant index 2b7d353b398..d20fa323abb 100644 --- a/stl/inc/variant +++ b/stl/inc/variant @@ -787,8 +787,7 @@ struct _Variant_construct_visitor { // visitor that constructs the same alternat _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); } } @@ -812,23 +811,23 @@ struct _Variant_assign_visitor { // visitor that implements assignment for varia (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); + _Variant_raw_get<_Idx>(_Self._Storage()) = 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); @@ -1242,11 +1241,10 @@ private: _CONSTEXPR20_DYNALLOC _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()); } _CONSTEXPR20_DYNALLOC void _Emplace_from(variant&& _That) noexcept( diff --git a/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp b/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp index 8f37cea2b87..a0939563bde 100644 --- a/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp +++ b/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp @@ -228,7 +228,35 @@ _CONSTEXPR20_DYNALLOC bool test_variant() { assert(get(move_assigned) == 42); } - { // emplace + { // 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); + } + +#ifndef __clang__ + { // emplace index T input{42}; variant emplace_copy; assert(emplace_copy.index() == 0); @@ -254,6 +282,7 @@ _CONSTEXPR20_DYNALLOC bool test_variant() { assert(emplace_initializer_list.index() == 1); assert(get(emplace_initializer_list) == 42); } +#endif // __clang__ { // swap variant left{T{42}}; From 4268ae05080c5818c2c2fedd7d633b72ef569a45 Mon Sep 17 00:00:00 2001 From: Michael Schellenberger Costa Date: Fri, 25 Jun 2021 12:27:25 +0200 Subject: [PATCH 12/38] finx invalid template emplace --- .../test.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp b/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp index a0939563bde..551e2be35f2 100644 --- a/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp +++ b/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp @@ -255,34 +255,32 @@ _CONSTEXPR20_DYNALLOC bool test_variant() { assert(get(emplace_initializer_list) == 42); } -#ifndef __clang__ { // emplace index T input{42}; variant emplace_copy; assert(emplace_copy.index() == 0); - emplace_copy.emplace<1>(input); + 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.emplace<1>(T{42}); + 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.emplace<1>(42); + 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.emplace<1>({42, 43}); + emplace_initializer_list.template emplace<1>({42, 43}); assert(emplace_initializer_list.index() == 1); assert(get(emplace_initializer_list) == 42); } -#endif // __clang__ { // swap variant left{T{42}}; From 3683d90971c3bc69a52d4d5e54c2db8f0c9d9889 Mon Sep 17 00:00:00 2001 From: Michael Schellenberger Costa Date: Fri, 25 Jun 2021 12:38:02 +0200 Subject: [PATCH 13/38] Be more consstent with the assignment operator --- stl/inc/variant | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stl/inc/variant b/stl/inc/variant index d20fa323abb..9d971a9b803 100644 --- a/stl/inc/variant +++ b/stl/inc/variant @@ -812,7 +812,8 @@ struct _Variant_assign_visitor { // visitor that implements assignment for varia _Self._Reset(); } else { if (_Self._Which == _Idx) { // same alternative: assign directly - _Variant_raw_get<_Idx>(_Self._Storage()) = 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>) { From 43ddb955f2363ba703fa2f0dd6dad14cfd8208ed Mon Sep 17 00:00:00 2001 From: Michael Schellenberger Costa Date: Fri, 25 Jun 2021 12:45:42 +0200 Subject: [PATCH 14/38] Minor cleanups --- stl/inc/variant | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/stl/inc/variant b/stl/inc/variant index 9d971a9b803..f32202883cc 100644 --- a/stl/inc/variant +++ b/stl/inc/variant @@ -837,9 +837,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); @@ -859,8 +858,8 @@ public: return _STD move(*this); } - _CONSTEXPR20_DYNALLOC _Variant_base() noexcept - : _Storage_t{}, _Which{_Invalid_index} {} // initialize to the value-less state + // initialize to the value-less state + _CONSTEXPR20_DYNALLOC _Variant_base() noexcept : _Storage_t{}, _Which{_Invalid_index} {} template , _Idx>, _UTypes...>, int> = 0> From d33b6c227711ba026acfc1a19aa745724b032ad6 Mon Sep 17 00:00:00 2001 From: Michael Schellenberger Costa Date: Fri, 25 Jun 2021 21:08:47 +0200 Subject: [PATCH 15/38] Work around DevCom-1331017 --- stl/inc/optional | 11 +++++---- stl/inc/variant | 3 +++ stl/inc/xsmf_control.h | 52 +++++++++++++++++++++--------------------- 3 files changed, 36 insertions(+), 30 deletions(-) diff --git a/stl/inc/optional b/stl/inc/optional index d5eae9afd62..ca65958bd62 100644 --- a/stl/inc/optional +++ b/stl/inc/optional @@ -95,10 +95,10 @@ struct _Optional_destruct_base<_Ty, false> { // either contains a value of _Ty o constexpr explicit _Optional_destruct_base(in_place_t, _Types&&... _Args) : _Value(_STD forward<_Types>(_Args)...), _Has_value{true} {} // initialize contained value with _Args... - _Optional_destruct_base(const _Optional_destruct_base&) = default; - _Optional_destruct_base(_Optional_destruct_base&&) = default; - _Optional_destruct_base& operator=(const _Optional_destruct_base&) = default; - _Optional_destruct_base& operator=(_Optional_destruct_base&&) = default; + constexpr _Optional_destruct_base(const _Optional_destruct_base&) = default; + constexpr _Optional_destruct_base(_Optional_destruct_base&&) = default; + constexpr _Optional_destruct_base& operator=(const _Optional_destruct_base&) = default; + constexpr _Optional_destruct_base& operator=(_Optional_destruct_base&&) = default; _CONSTEXPR20_DYNALLOC void reset() noexcept { if (_Has_value) { @@ -256,6 +256,9 @@ public: } #endif // ^^^ !_HAS_CONDITIONAL_EXPLICIT ^^^ + // TRANSITION, DevCom-1331017 + _CONSTEXPR20_DYNALLOC optional& operator=(const optional&) noexcept = default; + // assignment [optional.object.assign] _CONSTEXPR20_DYNALLOC optional& operator=(nullopt_t) noexcept { reset(); diff --git a/stl/inc/variant b/stl/inc/variant index f32202883cc..ebce28d5231 100644 --- a/stl/inc/variant +++ b/stl/inc/variant @@ -1092,6 +1092,9 @@ public: // initialize alternative _Idx from _Ilist and _Args... } + // TRANSITION, DevCom-1331017 + _CONSTEXPR20_DYNALLOC variant& operator=(const variant&) noexcept = default; + // assignment [variant.assign] template , variant> // && is_constructible_v<_Variant_init_type<_Ty, _Types...>, _Ty> // diff --git a/stl/inc/xsmf_control.h b/stl/inc/xsmf_control.h index 179db0f6fa9..b46dd3b0cd0 100644 --- a/stl/inc/xsmf_control.h +++ b/stl/inc/xsmf_control.h @@ -25,14 +25,14 @@ template struct _Non_trivial_copy : _Base { // non-trivial copy construction facade using _Base::_Base; - _Non_trivial_copy() = default; + constexpr _Non_trivial_copy() = default; _CONSTEXPR20_DYNALLOC _Non_trivial_copy(const _Non_trivial_copy& _That) noexcept( noexcept(_Base::_Construct_from(static_cast(_That)))) { _Base::_Construct_from(static_cast(_That)); } - _Non_trivial_copy(_Non_trivial_copy&&) = default; - _Non_trivial_copy& operator=(const _Non_trivial_copy&) = default; - _Non_trivial_copy& operator=(_Non_trivial_copy&&) = default; + constexpr _Non_trivial_copy(_Non_trivial_copy&&) = default; + constexpr _Non_trivial_copy& operator=(const _Non_trivial_copy&) = default; + constexpr _Non_trivial_copy& operator=(_Non_trivial_copy&&) = default; }; template @@ -47,14 +47,14 @@ struct _Non_trivial_move : _SMF_control_copy<_Base, _Types...> { // non-trivial using _Mybase = _SMF_control_copy<_Base, _Types...>; using _Mybase::_Mybase; - _Non_trivial_move() = default; - _Non_trivial_move(const _Non_trivial_move&) = default; + constexpr _Non_trivial_move() = default; + constexpr _Non_trivial_move(const _Non_trivial_move&) = default; _CONSTEXPR20_DYNALLOC _Non_trivial_move(_Non_trivial_move&& _That) noexcept( noexcept(_Mybase::_Construct_from(static_cast<_Base&&>(_That)))) { _Mybase::_Construct_from(static_cast<_Base&&>(_That)); } - _Non_trivial_move& operator=(const _Non_trivial_move&) = default; - _Non_trivial_move& operator=(_Non_trivial_move&&) = default; + constexpr _Non_trivial_move& operator=(const _Non_trivial_move&) = default; + constexpr _Non_trivial_move& operator=(_Non_trivial_move&&) = default; }; template @@ -69,16 +69,16 @@ struct _Non_trivial_copy_assign : _SMF_control_move<_Base, _Types...> { // non-t using _Mybase = _SMF_control_move<_Base, _Types...>; using _Mybase::_Mybase; - _Non_trivial_copy_assign() = default; - _Non_trivial_copy_assign(const _Non_trivial_copy_assign&) = default; - _Non_trivial_copy_assign(_Non_trivial_copy_assign&&) = default; + constexpr _Non_trivial_copy_assign() = default; + constexpr _Non_trivial_copy_assign(const _Non_trivial_copy_assign&) = default; + constexpr _Non_trivial_copy_assign(_Non_trivial_copy_assign&&) = default; _CONSTEXPR20_DYNALLOC _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; } - _Non_trivial_copy_assign& operator=(_Non_trivial_copy_assign&&) = default; + constexpr _Non_trivial_copy_assign& operator=(_Non_trivial_copy_assign&&) = default; }; template @@ -86,11 +86,11 @@ struct _Deleted_copy_assign : _SMF_control_move<_Base, _Types...> { // deleted c using _Mybase = _SMF_control_move<_Base, _Types...>; using _Mybase::_Mybase; - _Deleted_copy_assign() = default; - _Deleted_copy_assign(const _Deleted_copy_assign&) = default; - _Deleted_copy_assign(_Deleted_copy_assign&&) = default; - _Deleted_copy_assign& operator=(const _Deleted_copy_assign&) = delete; - _Deleted_copy_assign& operator=(_Deleted_copy_assign&&) = default; + constexpr _Deleted_copy_assign() = default; + constexpr _Deleted_copy_assign(const _Deleted_copy_assign&) = default; + constexpr _Deleted_copy_assign(_Deleted_copy_assign&&) = default; + constexpr _Deleted_copy_assign& operator=(const _Deleted_copy_assign&) = delete; + constexpr _Deleted_copy_assign& operator=(_Deleted_copy_assign&&) = default; }; template @@ -108,10 +108,10 @@ struct _Non_trivial_move_assign : _SMF_control_copy_assign<_Base, _Types...> { / using _Mybase = _SMF_control_copy_assign<_Base, _Types...>; using _Mybase::_Mybase; - _Non_trivial_move_assign() = default; - _Non_trivial_move_assign(const _Non_trivial_move_assign&) = default; - _Non_trivial_move_assign(_Non_trivial_move_assign&&) = default; - _Non_trivial_move_assign& operator=(const _Non_trivial_move_assign&) = default; + constexpr _Non_trivial_move_assign() = default; + constexpr _Non_trivial_move_assign(const _Non_trivial_move_assign&) = default; + constexpr _Non_trivial_move_assign(_Non_trivial_move_assign&&) = default; + constexpr _Non_trivial_move_assign& operator=(const _Non_trivial_move_assign&) = default; _CONSTEXPR20_DYNALLOC _Non_trivial_move_assign& operator=(_Non_trivial_move_assign&& _That) noexcept( noexcept(_Mybase::_Assign_from(static_cast<_Base&&>(_That)))) { @@ -125,11 +125,11 @@ struct _Deleted_move_assign : _SMF_control_copy_assign<_Base, _Types...> { // de using _Mybase = _SMF_control_copy_assign<_Base, _Types...>; using _Mybase::_Mybase; - _Deleted_move_assign() = default; - _Deleted_move_assign(const _Deleted_move_assign&) = default; - _Deleted_move_assign(_Deleted_move_assign&&) = default; - _Deleted_move_assign& operator=(const _Deleted_move_assign&) = default; - _Deleted_move_assign& operator=(_Deleted_move_assign&&) = delete; + constexpr _Deleted_move_assign() = default; + constexpr _Deleted_move_assign(const _Deleted_move_assign&) = default; + constexpr _Deleted_move_assign(_Deleted_move_assign&&) = default; + constexpr _Deleted_move_assign& operator=(const _Deleted_move_assign&) = default; + constexpr _Deleted_move_assign& operator=(_Deleted_move_assign&&) = delete; }; template From 3c820d73c01042d14ecb3f8da9ec499faa68247c Mon Sep 17 00:00:00 2001 From: Michael Schellenberger Costa Date: Fri, 25 Jun 2021 21:36:02 +0200 Subject: [PATCH 16/38] Do not work with an empty dumy struct --- .../P2231R1_complete_constexpr_optional_variant/test.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp b/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp index 551e2be35f2..bad87e714cf 100644 --- a/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp +++ b/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp @@ -30,7 +30,9 @@ struct With_nontrivial_destrutor { } }; -struct Dummy {}; +struct Dummy { + int _val = 0; +}; template _CONSTEXPR20_DYNALLOC bool test_optional() { From 8e7f2ab9afc7c1dd7254c7861aa35eff409347b7 Mon Sep 17 00:00:00 2001 From: Michael Schellenberger Costa Date: Sun, 4 Jul 2021 13:16:45 +0200 Subject: [PATCH 17/38] Unblock for clang / EDG --- stl/inc/optional | 37 ++++++------ stl/inc/variant | 56 +++++++++---------- stl/inc/xsmf_control.h | 52 ++++++++--------- stl/inc/yvals_core.h | 16 +++++- .../test.cpp | 14 +++-- .../test.compile.pass.cpp | 6 +- 6 files changed, 97 insertions(+), 84 deletions(-) diff --git a/stl/inc/optional b/stl/inc/optional index 55bc394ec41..51f1667a16e 100644 --- a/stl/inc/optional +++ b/stl/inc/optional @@ -70,7 +70,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... - _CONSTEXPR20_DYNALLOC void reset() noexcept { + _CONSTEXPR20_OPTIONAL void reset() noexcept { _Has_value = false; } }; @@ -83,7 +83,7 @@ struct _Optional_destruct_base<_Ty, false> { // either contains a value of _Ty o }; bool _Has_value; - _CONSTEXPR20_DYNALLOC ~_Optional_destruct_base() noexcept { + _CONSTEXPR20_OPTIONAL ~_Optional_destruct_base() noexcept { if (_Has_value) { _Destroy_in_place(_Value); } @@ -100,7 +100,7 @@ struct _Optional_destruct_base<_Ty, false> { // either contains a value of _Ty o constexpr _Optional_destruct_base& operator=(const _Optional_destruct_base&) = default; constexpr _Optional_destruct_base& operator=(_Optional_destruct_base&&) = default; - _CONSTEXPR20_DYNALLOC void reset() noexcept { + _CONSTEXPR20_OPTIONAL void reset() noexcept { if (_Has_value) { _Destroy_in_place(_Value); _Has_value = false; @@ -114,7 +114,7 @@ struct _Optional_construct_base : _Optional_destruct_base<_Ty> { using _Optional_destruct_base<_Ty>::_Optional_destruct_base; template - _CONSTEXPR20_DYNALLOC _Ty& _Construct(_Types&&... _Args) { + _CONSTEXPR20_OPTIONAL _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)...); @@ -123,7 +123,7 @@ struct _Optional_construct_base : _Optional_destruct_base<_Ty> { } template - _CONSTEXPR20_DYNALLOC void _Assign(_Ty2&& _Right) { // assign / initialize the contained value from _Right + _CONSTEXPR20_OPTIONAL void _Assign(_Ty2&& _Right) { // assign / initialize the contained value from _Right if (this->_Has_value) { this->_Value = _STD forward<_Ty2>(_Right); } else { @@ -132,7 +132,7 @@ struct _Optional_construct_base : _Optional_destruct_base<_Ty> { } template - _CONSTEXPR20_DYNALLOC void _Construct_from(_Self&& _Right) noexcept( + _CONSTEXPR20_OPTIONAL 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) { @@ -141,7 +141,7 @@ struct _Optional_construct_base : _Optional_destruct_base<_Ty> { } template - _CONSTEXPR20_DYNALLOC void _Assign_from(_Self&& _Right) noexcept( + _CONSTEXPR20_OPTIONAL 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 @@ -206,7 +206,7 @@ public: #if _HAS_CONDITIONAL_EXPLICIT template , is_constructible<_Ty, const _Ty2&>>, int> = 0> - _CONSTEXPR20_DYNALLOC explicit(!is_convertible_v) optional(const optional<_Ty2>& _Right) { + _CONSTEXPR20_OPTIONAL explicit(!is_convertible_v) optional(const optional<_Ty2>& _Right) { if (_Right) { this->_Construct(*_Right); } @@ -232,7 +232,7 @@ public: #if _HAS_CONDITIONAL_EXPLICIT template , is_constructible<_Ty, _Ty2>>, int> = 0> - _CONSTEXPR20_DYNALLOC explicit(!is_convertible_v<_Ty2, _Ty>) optional(optional<_Ty2>&& _Right) { + _CONSTEXPR20_OPTIONAL explicit(!is_convertible_v<_Ty2, _Ty>) optional(optional<_Ty2>&& _Right) { if (_Right) { this->_Construct(_STD move(*_Right)); } @@ -256,11 +256,8 @@ public: } #endif // ^^^ !_HAS_CONDITIONAL_EXPLICIT ^^^ - // TRANSITION, DevCom-1331017 - _CONSTEXPR20_DYNALLOC optional& operator=(const optional&) noexcept = default; - // assignment [optional.object.assign] - _CONSTEXPR20_DYNALLOC optional& operator=(nullopt_t) noexcept { + _CONSTEXPR20_OPTIONAL optional& operator=(nullopt_t) noexcept { reset(); return *this; } @@ -269,7 +266,7 @@ public: negation, is_same<_Ty, decay_t<_Ty2>>>>, is_constructible<_Ty, _Ty2>, is_assignable<_Ty&, _Ty2>>, int> = 0> - _CONSTEXPR20_DYNALLOC optional& operator=(_Ty2&& _Right) { + _CONSTEXPR20_OPTIONAL optional& operator=(_Ty2&& _Right) { this->_Assign(_STD forward<_Ty2>(_Right)); return *this; } @@ -283,7 +280,7 @@ public: template , is_constructible<_Ty, const _Ty2&>, is_assignable<_Ty&, const _Ty2&>>, int> = 0> - _CONSTEXPR20_DYNALLOC optional& operator=(const optional<_Ty2>& _Right) { + _CONSTEXPR20_OPTIONAL optional& operator=(const optional<_Ty2>& _Right) { if (_Right) { this->_Assign(*_Right); } else { @@ -296,7 +293,7 @@ public: template , is_constructible<_Ty, _Ty2>, is_assignable<_Ty&, _Ty2>>, int> = 0> - _CONSTEXPR20_DYNALLOC optional& operator=(optional<_Ty2>&& _Right) { + _CONSTEXPR20_OPTIONAL optional& operator=(optional<_Ty2>&& _Right) { if (_Right) { this->_Assign(_STD move(*_Right)); } else { @@ -307,20 +304,20 @@ public: } template - _CONSTEXPR20_DYNALLOC _Ty& emplace(_Types&&... _Args) { + _CONSTEXPR20_OPTIONAL _Ty& emplace(_Types&&... _Args) { reset(); return this->_Construct(_STD forward<_Types>(_Args)...); } template &, _Types...>, int> = 0> - _CONSTEXPR20_DYNALLOC _Ty& emplace(initializer_list<_Elem> _Ilist, _Types&&... _Args) { + _CONSTEXPR20_OPTIONAL _Ty& emplace(initializer_list<_Elem> _Ilist, _Types&&... _Args) { reset(); return this->_Construct(_Ilist, _STD forward<_Types>(_Args)...); } // swap [optional.object.swap] - _CONSTEXPR20_DYNALLOC void swap(optional& _Right) noexcept( + _CONSTEXPR20_OPTIONAL 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)."); @@ -664,7 +661,7 @@ _NODISCARD constexpr compare_three_way_result_t<_Ty1, _Ty2> // FUNCTION TEMPLATE swap [optional.specalg] template && is_swappable_v<_Ty>, int> = 0> -_CONSTEXPR20_DYNALLOC void swap(optional<_Ty>& _Left, optional<_Ty>& _Right) noexcept(noexcept(_Left.swap(_Right))) { +_CONSTEXPR20_OPTIONAL 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 ebce28d5231..36479c6b9bb 100644 --- a/stl/inc/variant +++ b/stl/inc/variant @@ -457,7 +457,7 @@ public: _Variant_storage<_Rest...> _Tail; }; - _CONSTEXPR20_DYNALLOC _Variant_storage_() noexcept {} // no initialization (no active member) + _CONSTEXPR20_VARIANT _Variant_storage_() noexcept {} // no initialization (no active member) template constexpr explicit _Variant_storage_(integral_constant, _Types&&... _Args) noexcept( @@ -492,12 +492,12 @@ public: _Variant_storage<_Rest...> _Tail; }; - _CONSTEXPR20_DYNALLOC ~_Variant_storage_() noexcept { + _CONSTEXPR20_VARIANT ~_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_DYNALLOC _Variant_storage_() noexcept {} // no initialization (no active member) + _CONSTEXPR20_VARIANT _Variant_storage_() noexcept {} // no initialization (no active member) template constexpr explicit _Variant_storage_(integral_constant, _Types&&... _Args) noexcept( @@ -549,12 +549,12 @@ public: _Variant_storage<_Rest...> _Tail; }; - _CONSTEXPR20_DYNALLOC ~_Variant_storage_() noexcept { + _CONSTEXPR20_VARIANT ~_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_DYNALLOC _Variant_storage_() noexcept {} // no initialization (no active member) + _CONSTEXPR20_VARIANT _Variant_storage_() noexcept {} // no initialization (no active member) template constexpr explicit _Variant_storage_(integral_constant, _Types&&... _Args) noexcept( @@ -781,7 +781,7 @@ struct _Variant_construct_visitor { // visitor that constructs the same alternat _Variant_base<_Types...>& _Self; template - _CONSTEXPR20_DYNALLOC void operator()(_Tagged<_Ty, _Idx> _Source) const noexcept( + _CONSTEXPR20_VARIANT 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()); @@ -802,7 +802,7 @@ struct _Variant_assign_visitor { // visitor that implements assignment for varia _Variant_base<_Types...>& _Self; template - _CONSTEXPR20_DYNALLOC void operator()(_Tagged<_Ty, _Idx> _Source) const + _CONSTEXPR20_VARIANT void operator()(_Tagged<_Ty, _Idx> _Source) const noexcept(disjunction_v, conjunction&, _Ty>, is_nothrow_constructible<_Remove_cvref_t<_Ty>, _Ty>>>) { @@ -859,7 +859,7 @@ public: } // initialize to the value-less state - _CONSTEXPR20_DYNALLOC _Variant_base() noexcept : _Storage_t{}, _Which{_Invalid_index} {} + _CONSTEXPR20_VARIANT _Variant_base() noexcept : _Storage_t{}, _Which{_Invalid_index} {} template , _Idx>, _UTypes...>, int> = 0> @@ -876,14 +876,14 @@ public: // index of the contained alternative or variant_npos if valueless_by_exception return static_cast(_Which); } - _CONSTEXPR20_DYNALLOC void _Set_index(const size_t _Idx) noexcept { + _CONSTEXPR20_VARIANT 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 - _CONSTEXPR20_DYNALLOC void _Destroy() noexcept { + _CONSTEXPR20_VARIANT void _Destroy() noexcept { // destroy the contained value // pre: _Idx == index() if constexpr (_Idx != variant_npos && !is_trivially_destructible_v<_Meta_at_c, _Idx>>) { @@ -891,7 +891,7 @@ public: } } - _CONSTEXPR20_DYNALLOC void _Destroy() noexcept { // destroy the contained value, if any + _CONSTEXPR20_VARIANT 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) { @@ -901,13 +901,13 @@ public: } } - _CONSTEXPR20_DYNALLOC void _Reset() noexcept { // transition to the valueless_by_exception state + _CONSTEXPR20_VARIANT void _Reset() noexcept { // transition to the valueless_by_exception state _Destroy(); _Set_index(variant_npos); } template - _CONSTEXPR20_DYNALLOC void _Reset() noexcept { + _CONSTEXPR20_VARIANT void _Reset() noexcept { // transition to the valueless_by_exception state // pre: _Idx == index() if constexpr (_Idx != variant_npos) { @@ -916,27 +916,27 @@ public: } } - _CONSTEXPR20_DYNALLOC void _Construct_from(const _Variant_base& _That) noexcept( + _CONSTEXPR20_VARIANT 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}); } - _CONSTEXPR20_DYNALLOC void _Construct_from(_Variant_base&& _That) noexcept( + _CONSTEXPR20_VARIANT 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}); } - _CONSTEXPR20_DYNALLOC void _Assign_from(const _Variant_base& _That) noexcept( + _CONSTEXPR20_VARIANT 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}); } - _CONSTEXPR20_DYNALLOC void _Assign_from(_Variant_base&& _That) noexcept( + _CONSTEXPR20_VARIANT 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}); @@ -947,7 +947,7 @@ template struct _Variant_destroy_layer_ : _Variant_base<_Types...> { // destruction behavior facade (non-trivial case) using _Variant_base<_Types...>::_Variant_base; - _CONSTEXPR20_DYNALLOC ~_Variant_destroy_layer_() noexcept { // Destroy contained value, if any + _CONSTEXPR20_VARIANT ~_Variant_destroy_layer_() noexcept { // Destroy contained value, if any this->_Destroy(); } @@ -1093,14 +1093,14 @@ public: } // TRANSITION, DevCom-1331017 - _CONSTEXPR20_DYNALLOC variant& operator=(const variant&) noexcept = default; + _CONSTEXPR20_VARIANT variant& operator=(const variant&) noexcept = default; // assignment [variant.assign] template , variant> // && is_constructible_v<_Variant_init_type<_Ty, _Types...>, _Ty> // && is_assignable_v<_Variant_init_type<_Ty, _Types...>&, _Ty>, // int> = 0> - _CONSTEXPR20_DYNALLOC variant& operator=(_Ty&& _Obj) noexcept( + _CONSTEXPR20_VARIANT 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)... @@ -1128,7 +1128,7 @@ public: template ::value, enable_if_t<_Idx != _Meta_npos && is_constructible_v<_Ty, _ArgTypes...>, int> = 0> - _CONSTEXPR20_DYNALLOC _Ty& emplace(_ArgTypes&&... _Args) noexcept( + _CONSTEXPR20_VARIANT _Ty& emplace(_ArgTypes&&... _Args) noexcept( is_nothrow_constructible_v<_Ty, _ArgTypes...>) /* strengthened */ { // emplace alternative _Ty from _Args... this->_Reset(); @@ -1136,7 +1136,7 @@ public: } template ::value, enable_if_t<_Idx != _Meta_npos && is_constructible_v<_Ty, initializer_list<_Elem>&, _ArgTypes...>, int> = 0> - _CONSTEXPR20_DYNALLOC _Ty& emplace(initializer_list<_Elem> _Ilist, _ArgTypes&&... _Args) noexcept( + _CONSTEXPR20_VARIANT _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(); @@ -1145,7 +1145,7 @@ public: template , _ArgTypes...>, int> = 0> - _CONSTEXPR20_DYNALLOC _Meta_at_c& emplace(_ArgTypes&&... _Args) noexcept( + _CONSTEXPR20_VARIANT _Meta_at_c& emplace(_ArgTypes&&... _Args) noexcept( is_nothrow_constructible_v<_Meta_at_c, _ArgTypes...>) /* strengthened */ { // emplace alternative _Idx from _Args... this->_Reset(); @@ -1153,7 +1153,7 @@ public: } template , initializer_list<_Elem>&, _ArgTypes...>, int> = 0> - _CONSTEXPR20_DYNALLOC _Meta_at_c& emplace(initializer_list<_Elem> _Ilist, + _CONSTEXPR20_VARIANT _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... @@ -1170,7 +1170,7 @@ public: #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunused-lambda-capture" #endif // TRANSITION, LLVM-45398 - _CONSTEXPR20_DYNALLOC void swap(variant& _That) noexcept( + _CONSTEXPR20_VARIANT 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 @@ -1241,7 +1241,7 @@ public: private: template - _CONSTEXPR20_DYNALLOC _Meta_at_c& _Emplace_valueless(_ArgTypes&&... _Args) noexcept( + _CONSTEXPR20_VARIANT _Meta_at_c& _Emplace_valueless(_ArgTypes&&... _Args) noexcept( is_nothrow_constructible_v<_Meta_at_c, _ArgTypes...>) { // initialize alternative _Idx from _Args... _STL_INTERNAL_CHECK(valueless_by_exception()); @@ -1250,7 +1250,7 @@ private: return _Variant_raw_get<_Idx>(_Storage()); } - _CONSTEXPR20_DYNALLOC void _Emplace_from(variant&& _That) noexcept( + _CONSTEXPR20_VARIANT void _Emplace_from(variant&& _That) noexcept( conjunction_v...>) { // steal the contained value from _That this->_Reset(); @@ -1757,7 +1757,7 @@ _NODISCARD constexpr bool operator>=(monostate, monostate) noexcept { // SPECIALIZED ALGORITHMS [variant.specalg] template ..., is_swappable<_Types>...>, int> = 0> -_CONSTEXPR20_DYNALLOC void swap(variant<_Types...>& _Left, variant<_Types...>& _Right) noexcept( +_CONSTEXPR20_VARIANT 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 b46dd3b0cd0..179db0f6fa9 100644 --- a/stl/inc/xsmf_control.h +++ b/stl/inc/xsmf_control.h @@ -25,14 +25,14 @@ template struct _Non_trivial_copy : _Base { // non-trivial copy construction facade using _Base::_Base; - constexpr _Non_trivial_copy() = default; + _Non_trivial_copy() = default; _CONSTEXPR20_DYNALLOC _Non_trivial_copy(const _Non_trivial_copy& _That) noexcept( noexcept(_Base::_Construct_from(static_cast(_That)))) { _Base::_Construct_from(static_cast(_That)); } - constexpr _Non_trivial_copy(_Non_trivial_copy&&) = default; - constexpr _Non_trivial_copy& operator=(const _Non_trivial_copy&) = default; - constexpr _Non_trivial_copy& operator=(_Non_trivial_copy&&) = default; + _Non_trivial_copy(_Non_trivial_copy&&) = default; + _Non_trivial_copy& operator=(const _Non_trivial_copy&) = default; + _Non_trivial_copy& operator=(_Non_trivial_copy&&) = default; }; template @@ -47,14 +47,14 @@ struct _Non_trivial_move : _SMF_control_copy<_Base, _Types...> { // non-trivial using _Mybase = _SMF_control_copy<_Base, _Types...>; using _Mybase::_Mybase; - constexpr _Non_trivial_move() = default; - constexpr _Non_trivial_move(const _Non_trivial_move&) = default; + _Non_trivial_move() = default; + _Non_trivial_move(const _Non_trivial_move&) = default; _CONSTEXPR20_DYNALLOC _Non_trivial_move(_Non_trivial_move&& _That) noexcept( noexcept(_Mybase::_Construct_from(static_cast<_Base&&>(_That)))) { _Mybase::_Construct_from(static_cast<_Base&&>(_That)); } - constexpr _Non_trivial_move& operator=(const _Non_trivial_move&) = default; - constexpr _Non_trivial_move& operator=(_Non_trivial_move&&) = default; + _Non_trivial_move& operator=(const _Non_trivial_move&) = default; + _Non_trivial_move& operator=(_Non_trivial_move&&) = default; }; template @@ -69,16 +69,16 @@ struct _Non_trivial_copy_assign : _SMF_control_move<_Base, _Types...> { // non-t using _Mybase = _SMF_control_move<_Base, _Types...>; using _Mybase::_Mybase; - constexpr _Non_trivial_copy_assign() = default; - constexpr _Non_trivial_copy_assign(const _Non_trivial_copy_assign&) = default; - constexpr _Non_trivial_copy_assign(_Non_trivial_copy_assign&&) = default; + _Non_trivial_copy_assign() = default; + _Non_trivial_copy_assign(const _Non_trivial_copy_assign&) = default; + _Non_trivial_copy_assign(_Non_trivial_copy_assign&&) = default; _CONSTEXPR20_DYNALLOC _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; } - constexpr _Non_trivial_copy_assign& operator=(_Non_trivial_copy_assign&&) = default; + _Non_trivial_copy_assign& operator=(_Non_trivial_copy_assign&&) = default; }; template @@ -86,11 +86,11 @@ struct _Deleted_copy_assign : _SMF_control_move<_Base, _Types...> { // deleted c using _Mybase = _SMF_control_move<_Base, _Types...>; using _Mybase::_Mybase; - constexpr _Deleted_copy_assign() = default; - constexpr _Deleted_copy_assign(const _Deleted_copy_assign&) = default; - constexpr _Deleted_copy_assign(_Deleted_copy_assign&&) = default; - constexpr _Deleted_copy_assign& operator=(const _Deleted_copy_assign&) = delete; - constexpr _Deleted_copy_assign& operator=(_Deleted_copy_assign&&) = default; + _Deleted_copy_assign() = default; + _Deleted_copy_assign(const _Deleted_copy_assign&) = default; + _Deleted_copy_assign(_Deleted_copy_assign&&) = default; + _Deleted_copy_assign& operator=(const _Deleted_copy_assign&) = delete; + _Deleted_copy_assign& operator=(_Deleted_copy_assign&&) = default; }; template @@ -108,10 +108,10 @@ struct _Non_trivial_move_assign : _SMF_control_copy_assign<_Base, _Types...> { / using _Mybase = _SMF_control_copy_assign<_Base, _Types...>; using _Mybase::_Mybase; - constexpr _Non_trivial_move_assign() = default; - constexpr _Non_trivial_move_assign(const _Non_trivial_move_assign&) = default; - constexpr _Non_trivial_move_assign(_Non_trivial_move_assign&&) = default; - constexpr _Non_trivial_move_assign& operator=(const _Non_trivial_move_assign&) = default; + _Non_trivial_move_assign() = default; + _Non_trivial_move_assign(const _Non_trivial_move_assign&) = default; + _Non_trivial_move_assign(_Non_trivial_move_assign&&) = default; + _Non_trivial_move_assign& operator=(const _Non_trivial_move_assign&) = default; _CONSTEXPR20_DYNALLOC _Non_trivial_move_assign& operator=(_Non_trivial_move_assign&& _That) noexcept( noexcept(_Mybase::_Assign_from(static_cast<_Base&&>(_That)))) { @@ -125,11 +125,11 @@ struct _Deleted_move_assign : _SMF_control_copy_assign<_Base, _Types...> { // de using _Mybase = _SMF_control_copy_assign<_Base, _Types...>; using _Mybase::_Mybase; - constexpr _Deleted_move_assign() = default; - constexpr _Deleted_move_assign(const _Deleted_move_assign&) = default; - constexpr _Deleted_move_assign(_Deleted_move_assign&&) = default; - constexpr _Deleted_move_assign& operator=(const _Deleted_move_assign&) = default; - constexpr _Deleted_move_assign& operator=(_Deleted_move_assign&&) = delete; + _Deleted_move_assign() = default; + _Deleted_move_assign(const _Deleted_move_assign&) = default; + _Deleted_move_assign(_Deleted_move_assign&&) = default; + _Deleted_move_assign& operator=(const _Deleted_move_assign&) = default; + _Deleted_move_assign& operator=(_Deleted_move_assign&&) = delete; }; template diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index 366e1743833..29e140cf9cf 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -1203,7 +1203,8 @@ #define __cpp_lib_node_extract 201606L #define __cpp_lib_not_fn 201603L -#if _HAS_CXX20 && defined(__cpp_constexpr_dynamic_alloc) // == __cpp_lib_constexpr_dynamic_alloc +#if _HAS_CXX20 && defined(__cpp_constexpr_dynamic_alloc) \ + && (defined(__clang__) || defined(__EDG) || defined(MSVC_INTERNAL_TESTING)) #define __cpp_lib_optional 202106L #else // ^^^ __cpp_lib_constexpr_dynamic_alloc ^^^ / vvv !__cpp_lib_constexpr_dynamic_alloc vvv #define __cpp_lib_optional 201606L @@ -1219,7 +1220,8 @@ #define __cpp_lib_string_view 201803L #define __cpp_lib_to_chars 201611L -#if _HAS_CXX20 && defined(__cpp_constexpr_dynamic_alloc) // == __cpp_lib_constexpr_dynamic_alloc +#if _HAS_CXX20 && defined(__cpp_constexpr_dynamic_alloc) \ + && (defined(__clang__) || defined(__EDG) || defined(MSVC_INTERNAL_TESTING)) #define __cpp_lib_variant 202106L #else // ^^^ __cpp_lib_constexpr_dynamic_alloc ^^^ / vvv !__cpp_lib_constexpr_dynamic_alloc vvv #define __cpp_lib_variant 202102L @@ -1387,6 +1389,16 @@ #define _CONSTEXPR20_DYNALLOC inline #endif +// optional / variant methods that became constexpr in C++20 via P2231 +#if defined(__cpp_lib_constexpr_dynamic_alloc) \ + && (defined(__clang__) || defined(__EDG__) || defined(MSVC_INTERNAL_TESTING)) +#define _CONSTEXPR20_OPTIONAL constexpr +#define _CONSTEXPR20_VARIANT constexpr +#else +#define _CONSTEXPR20_OPTIONAL inline +#define _CONSTEXPR20_VARIANT inline +#endif + // Functions that became constexpr in C++20 via P0980R1 or P1004R2 #if defined(__cpp_lib_constexpr_dynamic_alloc) && !defined(__clang__) // TRANSITION, LLVM-48606 #define _CONSTEXPR20_CONTAINER constexpr diff --git a/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp b/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp index bad87e714cf..f26ddda1152 100644 --- a/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp +++ b/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp @@ -35,7 +35,7 @@ struct Dummy { }; template -_CONSTEXPR20_DYNALLOC bool test_optional() { +_CONSTEXPR20_OPTIONAL bool test_optional() { { // empty construction optional defaut_constructed; assert(!defaut_constructed.has_value()); @@ -180,7 +180,7 @@ _CONSTEXPR20_DYNALLOC bool test_optional() { } template -_CONSTEXPR20_DYNALLOC bool test_variant() { +_CONSTEXPR20_VARIANT bool test_variant() { { // construction from underlying type const T input{42}; variant copy_constructed{input}; @@ -307,15 +307,17 @@ _CONSTEXPR20_DYNALLOC bool test_variant() { int main() { test_optional(); test_optional(); -#ifdef __cpp_lib_constexpr_dynamic_alloc +#if defined(__cpp_lib_constexpr_dynamic_alloc) \ + && (defined(__clang__) || defined(__EDG__) || defined(MSVC_INTERNAL_TESTING)) static_assert(test_optional()); static_assert(test_optional()); -#endif // __cpp_lib_constexpr_dynamic_alloc +#endif // __cpp_lib_constexpr_dynamic_alloc && (__clang__ || __EDG__ || MSVC_INTERNAL_TESTING) test_variant(); test_variant(); -#ifdef __cpp_lib_constexpr_dynamic_alloc +#if defined(__cpp_lib_constexpr_dynamic_alloc) \ + && (defined(__clang__) || defined(__EDG__) || defined(MSVC_INTERNAL_TESTING)) static_assert(test_variant()); static_assert(test_variant()); -#endif // __cpp_lib_constexpr_dynamic_alloc +#endif // __cpp_lib_constexpr_dynamic_alloc && (__clang__ || __EDG__ || MSVC_INTERNAL_TESTING) } 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 c16cbb73067..45749e2df25 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 @@ -1171,7 +1171,8 @@ STATIC_ASSERT(__cpp_lib_not_fn == 201603L); STATIC_ASSERT(__cpp_lib_null_iterators == 201304L); #endif -#ifdef __cpp_lib_constexpr_dynamic_alloc +#if defined(__cpp_lib_constexpr_dynamic_alloc) \ + && (defined(__clang__) || defined(__EDG__) || defined(MSVC_INTERNAL_TESTING)) #ifndef __cpp_lib_optional #error __cpp_lib_optional is not defined #elif __cpp_lib_optional != 202106L @@ -1669,7 +1670,8 @@ STATIC_ASSERT(__cpp_lib_unwrap_ref == 201811L); #endif #endif -#ifdef __cpp_lib_constexpr_dynamic_alloc +#if defined(__cpp_lib_constexpr_dynamic_alloc) \ + && (defined(__clang__) || defined(__EDG__) || defined(MSVC_INTERNAL_TESTING)) #ifndef __cpp_lib_variant #error __cpp_lib_variant is not defined #elif __cpp_lib_variant != 202106L From 692580ffad6af9a23f1d46f7c31bd15de63c5c17 Mon Sep 17 00:00:00 2001 From: Michael Schellenberger Costa Date: Sun, 4 Jul 2021 13:22:54 +0200 Subject: [PATCH 18/38] Minor bugfix --- stl/inc/optional | 8 ++++---- stl/inc/yvals_core.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/stl/inc/optional b/stl/inc/optional index 51f1667a16e..e4561370173 100644 --- a/stl/inc/optional +++ b/stl/inc/optional @@ -95,10 +95,10 @@ struct _Optional_destruct_base<_Ty, false> { // either contains a value of _Ty o constexpr explicit _Optional_destruct_base(in_place_t, _Types&&... _Args) : _Value(_STD forward<_Types>(_Args)...), _Has_value{true} {} // initialize contained value with _Args... - constexpr _Optional_destruct_base(const _Optional_destruct_base&) = default; - constexpr _Optional_destruct_base(_Optional_destruct_base&&) = default; - constexpr _Optional_destruct_base& operator=(const _Optional_destruct_base&) = default; - constexpr _Optional_destruct_base& operator=(_Optional_destruct_base&&) = default; + _Optional_destruct_base(const _Optional_destruct_base&) = default; + _Optional_destruct_base(_Optional_destruct_base&&) = default; + _Optional_destruct_base& operator=(const _Optional_destruct_base&) = default; + _Optional_destruct_base& operator=(_Optional_destruct_base&&) = default; _CONSTEXPR20_OPTIONAL void reset() noexcept { if (_Has_value) { diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index 29e140cf9cf..aedd1691879 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -1204,7 +1204,7 @@ #define __cpp_lib_not_fn 201603L #if _HAS_CXX20 && defined(__cpp_constexpr_dynamic_alloc) \ - && (defined(__clang__) || defined(__EDG) || defined(MSVC_INTERNAL_TESTING)) + && (defined(__clang__) || defined(__EDG__) || defined(MSVC_INTERNAL_TESTING)) #define __cpp_lib_optional 202106L #else // ^^^ __cpp_lib_constexpr_dynamic_alloc ^^^ / vvv !__cpp_lib_constexpr_dynamic_alloc vvv #define __cpp_lib_optional 201606L @@ -1221,7 +1221,7 @@ #define __cpp_lib_to_chars 201611L #if _HAS_CXX20 && defined(__cpp_constexpr_dynamic_alloc) \ - && (defined(__clang__) || defined(__EDG) || defined(MSVC_INTERNAL_TESTING)) + && (defined(__clang__) || defined(__EDG__) || defined(MSVC_INTERNAL_TESTING)) #define __cpp_lib_variant 202106L #else // ^^^ __cpp_lib_constexpr_dynamic_alloc ^^^ / vvv !__cpp_lib_constexpr_dynamic_alloc vvv #define __cpp_lib_variant 202102L From 4a1c79eaeeb327154292001b6d583b75e0bb5a9a Mon Sep 17 00:00:00 2001 From: Michael Schellenberger Costa Date: Sun, 4 Jul 2021 16:32:17 +0200 Subject: [PATCH 19/38] Remove workaround as we do not enable the feature for MSVC --- stl/inc/variant | 3 --- 1 file changed, 3 deletions(-) diff --git a/stl/inc/variant b/stl/inc/variant index 36479c6b9bb..34bf94394cd 100644 --- a/stl/inc/variant +++ b/stl/inc/variant @@ -1092,9 +1092,6 @@ public: // initialize alternative _Idx from _Ilist and _Args... } - // TRANSITION, DevCom-1331017 - _CONSTEXPR20_VARIANT variant& operator=(const variant&) noexcept = default; - // assignment [variant.assign] template , variant> // && is_constructible_v<_Variant_init_type<_Ty, _Types...>, _Ty> // From 2fe73d67f32a4f5f62887e80b95d2c57f8194a20 Mon Sep 17 00:00:00 2001 From: Michael Schellenberger Costa Date: Mon, 5 Jul 2021 11:05:50 +0200 Subject: [PATCH 20/38] Fix test --- tests/std/tests/P0220R1_optional/test.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/std/tests/P0220R1_optional/test.cpp b/tests/std/tests/P0220R1_optional/test.cpp index f25212ff432..23054d84616 100644 --- a/tests/std/tests/P0220R1_optional/test.cpp +++ b/tests/std/tests/P0220R1_optional/test.cpp @@ -4596,11 +4596,7 @@ int run_test() typedef X T; static_assert(!std::is_trivially_destructible::value, ""); static_assert(!std::is_trivially_destructible>::value, ""); - #ifdef __cpp_lib_constexpr_dynamic_alloc - static_assert(std::is_literal_type>::value, ""); - #else // ^^^ __cpp_lib_constexpr_dynamic_alloc ^^^ / vvv !__cpp_lib_constexpr_dynamic_alloc vvv static_assert(!std::is_literal_type>::value, ""); - #endif // !__cpp_lib_constexpr_dynamic_alloc { X x; optional opt{x}; From 7e7867ca224be67be0bf7e7872e9b9baaf4f82f8 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 6 Aug 2021 17:30:23 -0700 Subject: [PATCH 21/38] Stealth merge conflict: `_CONSTEXPR20_DYNALLOC` to `_CONSTEXPR20`. --- stl/inc/xsmf_control.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stl/inc/xsmf_control.h b/stl/inc/xsmf_control.h index 79c3e091272..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; - _CONSTEXPR20_DYNALLOC _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; - _CONSTEXPR20_DYNALLOC _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; - _CONSTEXPR20_DYNALLOC _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; - _CONSTEXPR20_DYNALLOC _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; From 89186b97372aa8bdd5fd193908210b69aeecdbba Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 6 Aug 2021 18:35:03 -0700 Subject: [PATCH 22/38] `_CONSTEXPR20_VARIANT` => `_CONSTEXPR20` in product code. --- stl/inc/variant | 60 ++++++++++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 31 deletions(-) diff --git a/stl/inc/variant b/stl/inc/variant index 85d777934d7..6a21afec4c0 100644 --- a/stl/inc/variant +++ b/stl/inc/variant @@ -434,7 +434,7 @@ public: _Variant_storage<_Rest...> _Tail; }; - _CONSTEXPR20_VARIANT _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,12 +469,12 @@ public: _Variant_storage<_Rest...> _Tail; }; - _CONSTEXPR20_VARIANT ~_Variant_storage_() noexcept { + _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) } - _CONSTEXPR20_VARIANT _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( @@ -526,12 +526,12 @@ public: _Variant_storage<_Rest...> _Tail; }; - _CONSTEXPR20_VARIANT ~_Variant_storage_() noexcept { + _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) } - _CONSTEXPR20_VARIANT _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( @@ -756,7 +756,7 @@ struct _Variant_construct_visitor { // visitor that constructs the same alternat _Variant_base<_Types...>& _Self; template - _CONSTEXPR20_VARIANT void operator()(_Tagged<_Ty, _Idx> _Source) const noexcept( + _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()); @@ -777,7 +777,7 @@ struct _Variant_assign_visitor { // visitor that implements assignment for varia _Variant_base<_Types...>& _Self; template - _CONSTEXPR20_VARIANT void operator()(_Tagged<_Ty, _Idx> _Source) const + _CONSTEXPR20 void operator()(_Tagged<_Ty, _Idx> _Source) const noexcept(disjunction_v, conjunction&, _Ty>, is_nothrow_constructible<_Remove_cvref_t<_Ty>, _Ty>>>) { @@ -834,7 +834,7 @@ public: } // initialize to the value-less state - _CONSTEXPR20_VARIANT _Variant_base() noexcept : _Storage_t{}, _Which{_Invalid_index} {} + _CONSTEXPR20 _Variant_base() noexcept : _Storage_t{}, _Which{_Invalid_index} {} template , _Idx>, _UTypes...>, int> = 0> @@ -851,14 +851,14 @@ public: // index of the contained alternative or variant_npos if valueless_by_exception return static_cast(_Which); } - _CONSTEXPR20_VARIANT 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 - _CONSTEXPR20_VARIANT 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>>) { @@ -866,7 +866,7 @@ public: } } - _CONSTEXPR20_VARIANT 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) { @@ -876,13 +876,13 @@ public: } } - _CONSTEXPR20_VARIANT 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 - _CONSTEXPR20_VARIANT void _Reset() noexcept { + _CONSTEXPR20 void _Reset() noexcept { // transition to the valueless_by_exception state // pre: _Idx == index() if constexpr (_Idx != variant_npos) { @@ -891,27 +891,27 @@ public: } } - _CONSTEXPR20_VARIANT void _Construct_from(const _Variant_base& _That) noexcept( + _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}); } - _CONSTEXPR20_VARIANT void _Construct_from(_Variant_base&& _That) noexcept( + _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}); } - _CONSTEXPR20_VARIANT 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}); } - _CONSTEXPR20_VARIANT 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}); @@ -922,7 +922,7 @@ template struct _Variant_destroy_layer_ : _Variant_base<_Types...> { // destruction behavior facade (non-trivial case) using _Variant_base<_Types...>::_Variant_base; - _CONSTEXPR20_VARIANT ~_Variant_destroy_layer_() noexcept { // Destroy contained value, if any + _CONSTEXPR20 ~_Variant_destroy_layer_() noexcept { // Destroy contained value, if any this->_Destroy(); } @@ -1069,7 +1069,7 @@ public: && is_constructible_v<_Variant_init_type<_Ty, _Types...>, _Ty> // && is_assignable_v<_Variant_init_type<_Ty, _Types...>&, _Ty>, // int> = 0> - _CONSTEXPR20_VARIANT variant& operator=(_Ty&& _Obj) noexcept( + _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)... @@ -1096,7 +1096,7 @@ public: template ::value, enable_if_t<_Idx != _Meta_npos && is_constructible_v<_Ty, _ArgTypes...>, int> = 0> - _CONSTEXPR20_VARIANT _Ty& emplace(_ArgTypes&&... _Args) noexcept( + _CONSTEXPR20 _Ty& emplace(_ArgTypes&&... _Args) noexcept( is_nothrow_constructible_v<_Ty, _ArgTypes...>) /* strengthened */ { // emplace alternative _Ty from _Args... this->_Reset(); @@ -1104,7 +1104,7 @@ public: } template ::value, enable_if_t<_Idx != _Meta_npos && is_constructible_v<_Ty, initializer_list<_Elem>&, _ArgTypes...>, int> = 0> - _CONSTEXPR20_VARIANT _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(); @@ -1113,7 +1113,7 @@ public: template , _ArgTypes...>, int> = 0> - _CONSTEXPR20_VARIANT _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(); @@ -1121,9 +1121,9 @@ public: } template , initializer_list<_Elem>&, _ArgTypes...>, int> = 0> - _CONSTEXPR20_VARIANT _Meta_at_c& emplace(initializer_list<_Elem> _Ilist, - _ArgTypes&&... _Args) noexcept(is_nothrow_constructible_v<_Meta_at_c, initializer_list<_Elem>&, - _ArgTypes...>) /* strengthened */ { + _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... this->_Reset(); return _Emplace_valueless<_Idx>(_Ilist, static_cast<_ArgTypes&&>(_Args)...); @@ -1136,7 +1136,7 @@ public: #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunused-lambda-capture" #endif // TRANSITION, LLVM-45398 - _CONSTEXPR20_VARIANT 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 @@ -1207,7 +1207,7 @@ public: private: template - _CONSTEXPR20_VARIANT _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... _STL_INTERNAL_CHECK(valueless_by_exception()); @@ -1216,8 +1216,7 @@ private: return _Variant_raw_get<_Idx>(_Storage()); } - _CONSTEXPR20_VARIANT 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(), @@ -1718,8 +1717,7 @@ _NODISCARD constexpr bool operator>=(monostate, monostate) noexcept { template ..., is_swappable<_Types>...>, int> = 0> -_CONSTEXPR20_VARIANT 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); } From 4f6046ff32c28751d282454641fb919e4f754f84 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 6 Aug 2021 18:35:51 -0700 Subject: [PATCH 23/38] Use `constexpr` unconditionally in `P2231R1_complete_constexpr_optional_variant/test.cpp`. --- .../P2231R1_complete_constexpr_optional_variant/test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp b/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp index f26ddda1152..53b4f38cdd7 100644 --- a/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp +++ b/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp @@ -35,7 +35,7 @@ struct Dummy { }; template -_CONSTEXPR20_OPTIONAL bool test_optional() { +constexpr bool test_optional() { { // empty construction optional defaut_constructed; assert(!defaut_constructed.has_value()); @@ -180,7 +180,7 @@ _CONSTEXPR20_OPTIONAL bool test_optional() { } template -_CONSTEXPR20_VARIANT bool test_variant() { +constexpr bool test_variant() { { // construction from underlying type const T input{42}; variant copy_constructed{input}; From 2a3d31edeb9933137c12efac34f833a433e0c40a Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 6 Aug 2021 19:12:22 -0700 Subject: [PATCH 24/38] Rework feature-test macros. --- stl/inc/yvals_core.h | 21 +++++-------------- .../test.compile.pass.cpp | 6 ++---- 2 files changed, 7 insertions(+), 20 deletions(-) diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index dbab9a6f2c6..28f791a2f1d 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -1205,14 +1205,6 @@ #define __cpp_lib_memory_resource 201603L #define __cpp_lib_node_extract 201606L #define __cpp_lib_not_fn 201603L - -#if _HAS_CXX20 && defined(__cpp_constexpr_dynamic_alloc) \ - && (defined(__clang__) || defined(__EDG__) || defined(MSVC_INTERNAL_TESTING)) -#define __cpp_lib_optional 202106L -#else // ^^^ __cpp_lib_constexpr_dynamic_alloc ^^^ / vvv !__cpp_lib_constexpr_dynamic_alloc vvv -#define __cpp_lib_optional 201606L -#endif // !__cpp_lib_constexpr_dynamic_alloc - #ifndef _M_CEE #define __cpp_lib_parallel_algorithm 201603L #endif // _M_CEE @@ -1222,13 +1214,6 @@ #define __cpp_lib_shared_ptr_weak_type 201606L #define __cpp_lib_string_view 201803L #define __cpp_lib_to_chars 201611L - -#if _HAS_CXX20 && defined(__cpp_constexpr_dynamic_alloc) \ - && (defined(__clang__) || defined(__EDG__) || defined(MSVC_INTERNAL_TESTING)) -#define __cpp_lib_variant 202106L -#else // ^^^ __cpp_lib_constexpr_dynamic_alloc ^^^ / vvv !__cpp_lib_constexpr_dynamic_alloc vvv -#define __cpp_lib_variant 202102L -#endif // !__cpp_lib_constexpr_dynamic_alloc #endif // _HAS_CXX17 // C++20 @@ -1340,8 +1325,12 @@ #if _HAS_CXX20 #define __cpp_lib_array_constexpr 201811L // P1032R1 Miscellaneous constexpr +#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_array_constexpr 201803L +#define __cpp_lib_array_constexpr 201803L // P0858R0 Constexpr Iterator Requirements +#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/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 89c11048800..5913fa17074 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 @@ -1185,8 +1185,7 @@ STATIC_ASSERT(__cpp_lib_not_fn == 201603L); STATIC_ASSERT(__cpp_lib_null_iterators == 201304L); #endif -#if defined(__cpp_lib_constexpr_dynamic_alloc) \ - && (defined(__clang__) || defined(__EDG__) || defined(MSVC_INTERNAL_TESTING)) +#if _HAS_CXX20 #ifndef __cpp_lib_optional #error __cpp_lib_optional is not defined #elif __cpp_lib_optional != 202106L @@ -1698,8 +1697,7 @@ STATIC_ASSERT(__cpp_lib_unwrap_ref == 201811L); #endif #endif -#if defined(__cpp_lib_constexpr_dynamic_alloc) \ - && (defined(__clang__) || defined(__EDG__) || defined(MSVC_INTERNAL_TESTING)) +#if _HAS_CXX20 #ifndef __cpp_lib_variant #error __cpp_lib_variant is not defined #elif __cpp_lib_variant != 202106L From 7b669888c98ed630a33071ef515031061835425f Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 6 Aug 2021 19:12:40 -0700 Subject: [PATCH 25/38] Update `is_literal_type>` test. --- tests/std/tests/P0220R1_optional/test.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/std/tests/P0220R1_optional/test.cpp b/tests/std/tests/P0220R1_optional/test.cpp index 23054d84616..6f09e42580b 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 _HAS_CXX20 && !defined(__clang__) // ***FIXME***, NOT YET INVESTIGATED! + // 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}; From cd2b0e017b4643fb871c65485cfe7511731880b5 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 6 Aug 2021 19:52:53 -0700 Subject: [PATCH 26/38] Update `tests/libcxx/expected_results.txt`. --- tests/libcxx/expected_results.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index d4840b28f55..c097754ded2 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -61,7 +61,7 @@ std/language.support/support.limits/support.limits.general/string_view.version.p # and fails the destructor tests for both std/language.support/support.limits/support.limits.general/optional.version.pass.cpp FAIL std/language.support/support.limits/support.limits.general/variant.version.pass.cpp FAIL -std/utilities/optional/optional.object/optional.object.dtor/dtor.pass.cpp FAIL +std/utilities/optional/optional.object/optional.object.dtor/dtor.pass.cpp:0 FAIL # test emits warning C4310: cast truncates constant value std/numerics/bit/bitops.rot/rotl.pass.cpp:0 FAIL From fa1535d9ac8c8688f08074e7f831fd09173b33fd Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 6 Aug 2021 20:40:03 -0700 Subject: [PATCH 27/38] 256 is now too big (32-bit Clang runs out of memory). --- tests/std/tests/P0088R3_variant/test.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/std/tests/P0088R3_variant/test.cpp b/tests/std/tests/P0088R3_variant/test.cpp index caa0c6c7955..127aa025608 100644 --- a/tests/std/tests/P0088R3_variant/test.cpp +++ b/tests/std/tests/P0088R3_variant/test.cpp @@ -6444,9 +6444,7 @@ 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 +#else // C1XX and Clang constexpr std::size_t big = 120; #endif // tune value of "big" to a bit less than the largest variant the front-end can handle constexpr std::size_t n = 16; From aac8599138a6553654e4a6cea8862165965b7569 Mon Sep 17 00:00:00 2001 From: Michael Schellenberger Costa Date: Sun, 8 Aug 2021 13:48:48 +0200 Subject: [PATCH 28/38] Disable constexpr optional / variant for MSVC --- stl/inc/yvals_core.h | 12 ++++++++---- .../test.cpp | 10 ++++------ .../test.compile.pass.cpp | 4 ++-- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index 28f791a2f1d..78ee65db27b 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -1325,14 +1325,18 @@ #if _HAS_CXX20 #define __cpp_lib_array_constexpr 201811L // P1032R1 Miscellaneous constexpr -#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_array_constexpr 201803L // P0858R0 Constexpr Iterator Requirements -#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(__clang__) || defined(__EDG__)) +#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 non MSVC / _HAS_CXX17 or MSVC vvv +#define __cpp_lib_optional 201606L // P0307R2 Making Optional Greater Equal Again +#define __cpp_lib_variant 202102L // P2162R2 Inheriting From variant +#endif // _HAS_CXX17 or MSVC vvv + #if _HAS_CXX20 && defined(__cpp_lib_concepts) // TRANSITION, GH-395 #define __cpp_lib_chrono 201907L // P1466R3 Miscellaneous Minor Fixes For #elif _HAS_CXX17 diff --git a/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp b/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp index 53b4f38cdd7..f4e10ee1210 100644 --- a/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp +++ b/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp @@ -307,17 +307,15 @@ constexpr bool test_variant() { int main() { test_optional(); test_optional(); -#if defined(__cpp_lib_constexpr_dynamic_alloc) \ - && (defined(__clang__) || defined(__EDG__) || defined(MSVC_INTERNAL_TESTING)) +#if defined(__clang__) || defined(__EDG__) static_assert(test_optional()); static_assert(test_optional()); -#endif // __cpp_lib_constexpr_dynamic_alloc && (__clang__ || __EDG__ || MSVC_INTERNAL_TESTING) +#endif // __clang__ || __EDG__ test_variant(); test_variant(); -#if defined(__cpp_lib_constexpr_dynamic_alloc) \ - && (defined(__clang__) || defined(__EDG__) || defined(MSVC_INTERNAL_TESTING)) +#if defined(__clang__) || defined(__EDG__) static_assert(test_variant()); static_assert(test_variant()); -#endif // __cpp_lib_constexpr_dynamic_alloc && (__clang__ || __EDG__ || MSVC_INTERNAL_TESTING) +#endif // __clang__ || __EDG__ } 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 5913fa17074..8fd070b34b5 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 @@ -1185,7 +1185,7 @@ STATIC_ASSERT(__cpp_lib_not_fn == 201603L); STATIC_ASSERT(__cpp_lib_null_iterators == 201304L); #endif -#if _HAS_CXX20 +#if _HAS_CXX20 && (defined(__clang__) || defined(__EDG__)) #ifndef __cpp_lib_optional #error __cpp_lib_optional is not defined #elif __cpp_lib_optional != 202106L @@ -1697,7 +1697,7 @@ STATIC_ASSERT(__cpp_lib_unwrap_ref == 201811L); #endif #endif -#if _HAS_CXX20 +#if _HAS_CXX20 && (defined(__clang__) || defined(__EDG__)) #ifndef __cpp_lib_variant #error __cpp_lib_variant is not defined #elif __cpp_lib_variant != 202106L From a2c4d945ead9aa641c80f15bc4909b23d002b9b8 Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Mon, 9 Aug 2021 16:52:12 -0700 Subject: [PATCH 29/38] Minor test cleanup * A 64-alternative variant is "big" enough. * Clang doesn't know yet that a union with at least one literal member is a literal type. --- tests/std/tests/P0088R3_variant/test.cpp | 2 +- tests/std/tests/P0220R1_optional/test.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/std/tests/P0088R3_variant/test.cpp b/tests/std/tests/P0088R3_variant/test.cpp index 127aa025608..486ed60d865 100644 --- a/tests/std/tests/P0088R3_variant/test.cpp +++ b/tests/std/tests/P0088R3_variant/test.cpp @@ -6445,7 +6445,7 @@ namespace msvc { #ifdef __EDG__ constexpr std::size_t big = 20; #else // C1XX and Clang - constexpr std::size_t big = 120; + 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 6f09e42580b..72f0928000a 100644 --- a/tests/std/tests/P0220R1_optional/test.cpp +++ b/tests/std/tests/P0220R1_optional/test.cpp @@ -4597,7 +4597,7 @@ int run_test() static_assert(!std::is_trivially_destructible::value, ""); static_assert(!std::is_trivially_destructible>::value, ""); -#if _HAS_CXX20 && !defined(__clang__) // ***FIXME***, NOT YET INVESTIGATED! +#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 From 4ab846ac0c89e96b4d9033efb9767b09e85fcd3e Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Thu, 12 Aug 2021 15:37:49 -0700 Subject: [PATCH 30/38] s/destrut/destruct/g --- .../test.cpp | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp b/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp index f4e10ee1210..82fd481e83c 100644 --- a/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp +++ b/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp @@ -9,21 +9,21 @@ using namespace std; -struct With_trivial_destrutor { +struct With_trivial_destructor { int _val = 0; - constexpr With_trivial_destrutor(const int val) noexcept : _val(val) {} - constexpr With_trivial_destrutor(initializer_list vals) noexcept : _val(*vals.begin()) {} + 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_destrutor { +struct With_nontrivial_destructor { int _val = 0; - constexpr With_nontrivial_destrutor(const int val) noexcept : _val(val) {} - constexpr With_nontrivial_destrutor(initializer_list vals) noexcept : _val(*vals.begin()) {} - constexpr ~With_nontrivial_destrutor() {} + 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; @@ -305,17 +305,17 @@ constexpr bool test_variant() { } int main() { - test_optional(); - test_optional(); + test_optional(); + test_optional(); #if defined(__clang__) || defined(__EDG__) - static_assert(test_optional()); - static_assert(test_optional()); + static_assert(test_optional()); + static_assert(test_optional()); #endif // __clang__ || __EDG__ - test_variant(); - test_variant(); + test_variant(); + test_variant(); #if defined(__clang__) || defined(__EDG__) - static_assert(test_variant()); - static_assert(test_variant()); + static_assert(test_variant()); + static_assert(test_variant()); #endif // __clang__ || __EDG__ } From 0d4d285a113454c19f1e0dde5fa98cbfd7fbf1bc Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Tue, 17 Aug 2021 09:09:23 -0700 Subject: [PATCH 31/38] Update skip lists --- tests/libcxx/expected_results.txt | 10 +++++----- tests/libcxx/skipped_tests.txt | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index c097754ded2..bc937767e4d 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -57,11 +57,8 @@ 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` and `__cpp_lib_variant` -# and fails the destructor tests for both -std/language.support/support.limits/support.limits.general/optional.version.pass.cpp FAIL -std/language.support/support.limits/support.limits.general/variant.version.pass.cpp FAIL -std/utilities/optional/optional.object/optional.object.dtor/dtor.pass.cpp:0 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 @@ -69,6 +66,9 @@ 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 7382b0c0fdb..8ccc009c11d 100644 --- a/tests/libcxx/skipped_tests.txt +++ b/tests/libcxx/skipped_tests.txt @@ -57,11 +57,8 @@ 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` and `__cpp_lib_variant` -# and fails the destructor tests for both +# 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 -language.support\support.limits\support.limits.general\variant.version.pass.cpp -utilities\optional\optional.object\optional.object.dtor\dtor.pass.cpp # test emits warning C4310: cast truncates constant value numerics\bit\bitops.rot\rotl.pass.cpp @@ -69,6 +66,9 @@ 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" From 5e75f52695f6d379c22df8d2cbab987dd3844ad2 Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Tue, 17 Aug 2021 11:25:48 -0700 Subject: [PATCH 32/38] typo "defaut_constructed" --- .../P2231R1_complete_constexpr_optional_variant/test.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp b/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp index 82fd481e83c..69ddbb7d327 100644 --- a/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp +++ b/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp @@ -37,8 +37,8 @@ struct Dummy { template constexpr bool test_optional() { { // empty construction - optional defaut_constructed; - assert(!defaut_constructed.has_value()); + optional default_constructed; + assert(!default_constructed.has_value()); optional nullopt_constructed{nullopt}; assert(!nullopt_constructed.has_value()); @@ -307,14 +307,14 @@ constexpr bool test_variant() { int main() { test_optional(); test_optional(); -#if defined(__clang__) || defined(__EDG__) +#if 1 // defined(__clang__) || defined(__EDG__) static_assert(test_optional()); static_assert(test_optional()); #endif // __clang__ || __EDG__ test_variant(); test_variant(); -#if defined(__clang__) || defined(__EDG__) +#if 1 // defined(__clang__) || defined(__EDG__) static_assert(test_variant()); static_assert(test_variant()); #endif // __clang__ || __EDG__ From ad71e32950325a31d76f3795f056d2c79ef31ac1 Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Tue, 17 Aug 2021 12:48:48 -0700 Subject: [PATCH 33/38] Annotate the bug avoidance conditions with "TRANSITION, FIXME" --- stl/inc/yvals_core.h | 6 +++--- .../P2231R1_complete_constexpr_optional_variant/test.cpp | 8 ++++---- .../VSO_0157762_feature_test_macros/test.compile.pass.cpp | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index 78ee65db27b..056714e12d2 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -1329,13 +1329,13 @@ #define __cpp_lib_array_constexpr 201803L // P0858R0 Constexpr Iterator Requirements #endif // _HAS_CXX17 -#if _HAS_CXX20 && (defined(__clang__) || defined(__EDG__)) +#if _HAS_CXX20 && (defined(__clang__) || defined(__EDG__)) // TRANSITION, FIXME #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 non MSVC / _HAS_CXX17 or MSVC vvv +#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 or MSVC vvv +#endif // _HAS_CXX17 #if _HAS_CXX20 && defined(__cpp_lib_concepts) // TRANSITION, GH-395 #define __cpp_lib_chrono 201907L // P1466R3 Miscellaneous Minor Fixes For diff --git a/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp b/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp index 69ddbb7d327..9f85b6c39f3 100644 --- a/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp +++ b/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp @@ -307,15 +307,15 @@ constexpr bool test_variant() { int main() { test_optional(); test_optional(); -#if 1 // defined(__clang__) || defined(__EDG__) +#if defined(__clang__) || defined(__EDG__) // TRANSITION, FIXME static_assert(test_optional()); static_assert(test_optional()); -#endif // __clang__ || __EDG__ +#endif // TRANSITION test_variant(); test_variant(); -#if 1 // defined(__clang__) || defined(__EDG__) +#if defined(__clang__) || defined(__EDG__) // TRANSITION, FIXME static_assert(test_variant()); static_assert(test_variant()); -#endif // __clang__ || __EDG__ +#endif // TRANSITION } 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 8fd070b34b5..32129cfa1ee 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 @@ -1185,7 +1185,7 @@ STATIC_ASSERT(__cpp_lib_not_fn == 201603L); STATIC_ASSERT(__cpp_lib_null_iterators == 201304L); #endif -#if _HAS_CXX20 && (defined(__clang__) || defined(__EDG__)) +#if _HAS_CXX20 && (defined(__clang__) || defined(__EDG__)) // TRANSITION, FIXME #ifndef __cpp_lib_optional #error __cpp_lib_optional is not defined #elif __cpp_lib_optional != 202106L @@ -1697,7 +1697,7 @@ STATIC_ASSERT(__cpp_lib_unwrap_ref == 201811L); #endif #endif -#if _HAS_CXX20 && (defined(__clang__) || defined(__EDG__)) +#if _HAS_CXX20 && (defined(__clang__) || defined(__EDG__)) // TRANSITION, FIXME #ifndef __cpp_lib_variant #error __cpp_lib_variant is not defined #elif __cpp_lib_variant != 202106L From 7bad01b3e284298a1a7a99d9bec2cce3b2aad46e Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Tue, 17 Aug 2021 14:20:46 -0700 Subject: [PATCH 34/38] Localize test failures --- .../test.cpp | 64 +++++++++++-------- 1 file changed, 38 insertions(+), 26 deletions(-) diff --git a/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp b/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp index 9f85b6c39f3..75d0c783bc5 100644 --- a/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp +++ b/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp @@ -103,17 +103,25 @@ constexpr bool test_optional() { assert(move_constructed.has_value()); assert(*move_constructed == 42); - optional copy_assigned; - assert(!copy_assigned.has_value()); - copy_assigned = constructed; - assert(copy_assigned.has_value()); - assert(*copy_assigned == 42); - - optional move_assigned; - assert(!move_assigned.has_value()); - move_assigned = move(constructed); - assert(move_assigned.has_value()); - assert(*move_assigned == 42); +#if !(defined(__clang__) || defined(__EDG__)) // TRANSITION, FIXME + if constexpr (!is_same_v) { + if (!is_constant_evaluated()) { +#endif // TRANSITION + optional copy_assigned; + assert(!copy_assigned.has_value()); + copy_assigned = constructed; + assert(copy_assigned.has_value()); + assert(*copy_assigned == 42); + + optional move_assigned; + assert(!move_assigned.has_value()); + move_assigned = move(constructed); + assert(move_assigned.has_value()); + assert(*move_assigned == 42); +#if !(defined(__clang__) || defined(__EDG__)) // TRANSITION, FIXME + } + } +#endif // TRANSITION, FIXME } { // construction from optional with convertible types @@ -217,17 +225,25 @@ constexpr bool test_variant() { assert(move_constructed.index() == 1); assert(get(move_constructed) == 42); - 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, FIXME + 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, FIXME + } + } +#endif // TRANSITION } { // emplace type @@ -307,15 +323,11 @@ constexpr bool test_variant() { int main() { test_optional(); test_optional(); -#if defined(__clang__) || defined(__EDG__) // TRANSITION, FIXME static_assert(test_optional()); static_assert(test_optional()); -#endif // TRANSITION test_variant(); test_variant(); -#if defined(__clang__) || defined(__EDG__) // TRANSITION, FIXME static_assert(test_variant()); static_assert(test_variant()); -#endif // TRANSITION } From 76dd30e4e4269a2fe85e63da09931ef244a101d4 Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Tue, 17 Aug 2021 14:43:14 -0700 Subject: [PATCH 35/38] The bug is, in fact, DevCom-1331017 --- stl/inc/yvals_core.h | 2 +- .../test.cpp | 10 +++++----- .../test.compile.pass.cpp | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index 056714e12d2..87a955d06b1 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -1329,7 +1329,7 @@ #define __cpp_lib_array_constexpr 201803L // P0858R0 Constexpr Iterator Requirements #endif // _HAS_CXX17 -#if _HAS_CXX20 && (defined(__clang__) || defined(__EDG__)) // TRANSITION, FIXME +#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 diff --git a/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp b/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp index 75d0c783bc5..8b4d8ab2981 100644 --- a/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp +++ b/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp @@ -103,7 +103,7 @@ constexpr bool test_optional() { assert(move_constructed.has_value()); assert(*move_constructed == 42); -#if !(defined(__clang__) || defined(__EDG__)) // TRANSITION, FIXME +#if !(defined(__clang__) || defined(__EDG__)) // TRANSITION, DevCom-1331017 if constexpr (!is_same_v) { if (!is_constant_evaluated()) { #endif // TRANSITION @@ -118,10 +118,10 @@ constexpr bool test_optional() { move_assigned = move(constructed); assert(move_assigned.has_value()); assert(*move_assigned == 42); -#if !(defined(__clang__) || defined(__EDG__)) // TRANSITION, FIXME +#if !(defined(__clang__) || defined(__EDG__)) // TRANSITION, DevCom-1331017 } } -#endif // TRANSITION, FIXME +#endif // TRANSITION, DevCom-1331017 } { // construction from optional with convertible types @@ -225,7 +225,7 @@ constexpr bool test_variant() { assert(move_constructed.index() == 1); assert(get(move_constructed) == 42); -#if !(defined(__clang__) || defined(__EDG__)) // TRANSITION, FIXME +#if !(defined(__clang__) || defined(__EDG__)) // TRANSITION, DevCom-1331017 if constexpr (!is_same_v) { if (!is_constant_evaluated()) { #endif // TRANSITION @@ -240,7 +240,7 @@ constexpr bool test_variant() { move_assigned = move(constructed); assert(move_assigned.index() == 1); assert(get(move_assigned) == 42); -#if !(defined(__clang__) || defined(__EDG__)) // TRANSITION, FIXME +#if !(defined(__clang__) || defined(__EDG__)) // TRANSITION, DevCom-1331017 } } #endif // TRANSITION 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 32129cfa1ee..92a41a90b5a 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 @@ -1185,7 +1185,7 @@ STATIC_ASSERT(__cpp_lib_not_fn == 201603L); STATIC_ASSERT(__cpp_lib_null_iterators == 201304L); #endif -#if _HAS_CXX20 && (defined(__clang__) || defined(__EDG__)) // TRANSITION, FIXME +#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 @@ -1697,7 +1697,7 @@ STATIC_ASSERT(__cpp_lib_unwrap_ref == 201811L); #endif #endif -#if _HAS_CXX20 && (defined(__clang__) || defined(__EDG__)) // TRANSITION, FIXME +#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 From 79fbac8c1668780b655f866496d2fb2c9233161d Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Tue, 17 Aug 2021 15:53:10 -0700 Subject: [PATCH 36/38] Update tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp Add missing include --- .../tests/P2231R1_complete_constexpr_optional_variant/test.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp b/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp index 8b4d8ab2981..e0ce4c1469c 100644 --- a/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp +++ b/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include From 3024814a78a165f4374009d81dc0453cd8a8d2ea Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 18 Aug 2021 17:53:15 -0700 Subject: [PATCH 37/38] Test `optional` construction from different `optional` types. --- .../test.cpp | 25 +++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp b/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp index e0ce4c1469c..09ed34f1dcc 100644 --- a/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp +++ b/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp @@ -126,16 +126,27 @@ constexpr bool test_optional() { } { // construction from optional with convertible types - optional constructed{42}; optional input{42}; - constructed = input; - assert(constructed.has_value()); - assert(*constructed == 42); + optional copy_constructed{input}; + assert(copy_constructed.has_value()); + assert(*copy_constructed == 42); - constructed = optional{3}; - assert(constructed.has_value()); - assert(*constructed == 3); + optional move_constructed{optional{3}}; + assert(move_constructed.has_value()); + assert(*move_constructed == 3); + + optional copy_assigned; + assert(!copy_assigned.has_value()); + copy_assigned = input; + assert(copy_assigned.has_value()); + assert(*copy_assigned == 42); + + optional move_assigned; + assert(!move_assigned.has_value()); + move_assigned = optional{3}; + assert(move_assigned.has_value()); + assert(*move_assigned == 3); } { // emplace From 36b929cba31aeb6645addd23a260657de7fc1296 Mon Sep 17 00:00:00 2001 From: Michael Schellenberger Costa Date: Tue, 24 Aug 2021 10:55:52 +0200 Subject: [PATCH 38/38] Rename all the things --- .../test.cpp | 156 +++++++++--------- 1 file changed, 78 insertions(+), 78 deletions(-) diff --git a/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp b/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp index 09ed34f1dcc..0f948a7ee5d 100644 --- a/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp +++ b/tests/std/tests/P2231R1_complete_constexpr_optional_variant/test.cpp @@ -47,48 +47,48 @@ constexpr bool test_optional() { { // construction from underlying type const T input{42}; - optional copy_constructed{input}; - assert(copy_constructed.has_value()); - assert(*copy_constructed == 42); - - optional move_constructed{T{42}}; - assert(move_constructed.has_value()); - assert(*move_constructed == 42); - - optional copy_assigned; - assert(!copy_assigned.has_value()); - copy_assigned = input; - assert(copy_assigned.has_value()); - assert(*copy_assigned == 42); - - optional move_assigned; - assert(!move_assigned.has_value()); - move_assigned = T{42}; - assert(move_assigned.has_value()); - assert(*move_assigned == 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 copy_constructed{input}; - assert(copy_constructed.has_value()); - assert(*copy_constructed == 42); - - optional move_constructed{42}; - assert(move_constructed.has_value()); - assert(*move_constructed == 42); - - optional copy_assigned; - assert(!copy_assigned.has_value()); - copy_assigned = input; - assert(copy_assigned.has_value()); - assert(*copy_assigned == 42); - - optional move_assigned; - assert(!move_assigned.has_value()); - move_assigned = 42; - assert(move_assigned.has_value()); - assert(*move_assigned == 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 @@ -110,13 +110,13 @@ constexpr bool test_optional() { #endif // TRANSITION optional copy_assigned; assert(!copy_assigned.has_value()); - copy_assigned = constructed; + copy_assigned = move_constructed; assert(copy_assigned.has_value()); assert(*copy_assigned == 42); optional move_assigned; assert(!move_assigned.has_value()); - move_assigned = move(constructed); + move_assigned = move(copy_assigned); assert(move_assigned.has_value()); assert(*move_assigned == 42); #if !(defined(__clang__) || defined(__EDG__)) // TRANSITION, DevCom-1331017 @@ -128,25 +128,25 @@ constexpr bool test_optional() { { // construction from optional with convertible types optional input{42}; - optional copy_constructed{input}; - assert(copy_constructed.has_value()); - assert(*copy_constructed == 42); - - optional move_constructed{optional{3}}; - assert(move_constructed.has_value()); - assert(*move_constructed == 3); - - optional copy_assigned; - assert(!copy_assigned.has_value()); - copy_assigned = input; - assert(copy_assigned.has_value()); - assert(*copy_assigned == 42); - - optional move_assigned; - assert(!move_assigned.has_value()); - move_assigned = optional{3}; - assert(move_assigned.has_value()); - assert(*move_assigned == 3); + 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 @@ -203,25 +203,25 @@ template constexpr bool test_variant() { { // construction from underlying type const T input{42}; - variant copy_constructed{input}; - assert(copy_constructed.index() == 1); - assert(get(copy_constructed) == 42); - - variant move_constructed{T{42}}; - assert(move_constructed.index() == 1); - assert(get(move_constructed) == 42); - - variant copy_assigned; - assert(copy_assigned.index() == 0); - copy_assigned = input; - assert(copy_assigned.index() == 1); - assert(get(copy_assigned) == 42); - - variant move_assigned; - assert(move_assigned.index() == 0); - move_assigned = T{42}; - assert(move_assigned.index() == 1); - assert(get(move_assigned) == 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