diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst --- a/libcxx/docs/FeatureTestMacroTable.rst +++ b/libcxx/docs/FeatureTestMacroTable.rst @@ -182,6 +182,8 @@ ------------------------------------------------- ----------------- ``__cpp_lib_constexpr_swap_algorithms`` *unimplemented* ------------------------------------------------- ----------------- + ``__cpp_lib_constexpr_utility `` ``201811L`` + ------------------------------------------------- ----------------- ``__cpp_lib_destroying_delete`` ``201806L`` ------------------------------------------------- ----------------- ``__cpp_lib_endian`` ``201907L`` diff --git a/libcxx/include/tuple b/libcxx/include/tuple --- a/libcxx/include/tuple +++ b/libcxx/include/tuple @@ -1393,7 +1393,7 @@ template template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 pair<_T1, _T2>::pair(piecewise_construct_t, tuple<_Args1...>& __first_args, tuple<_Args2...>& __second_args, __tuple_indices<_I1...>, __tuple_indices<_I2...>) diff --git a/libcxx/include/utility b/libcxx/include/utility --- a/libcxx/include/utility +++ b/libcxx/include/utility @@ -499,7 +499,7 @@ second(_VSTD::get<1>(_VSTD::forward<_Tuple>(__p))) {} template - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 pair(piecewise_construct_t __pc, tuple<_Args1...> __first_args, tuple<_Args2...> __second_args) _NOEXCEPT_((is_nothrow_constructible::value && @@ -508,7 +508,7 @@ typename __make_tuple_indices::type(), typename __make_tuple_indices::type()) {} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 pair& operator=(typename conditional< is_copy_assignable::value && is_copy_assignable::value, @@ -521,7 +521,7 @@ return *this; } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 pair& operator=(typename conditional< is_move_assignable::value && is_move_assignable::value, @@ -537,7 +537,7 @@ template ::template __enable_assign<_Tuple>() > = false> - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 pair& operator=(_Tuple&& __p) { first = _VSTD::get<0>(_VSTD::forward<_Tuple>(__p)); second = _VSTD::get<1>(_VSTD::forward<_Tuple>(__p)); @@ -545,7 +545,7 @@ } #endif - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void swap(pair& __p) _NOEXCEPT_(__is_nothrow_swappable::value && __is_nothrow_swappable::value) @@ -558,10 +558,10 @@ #ifndef _LIBCPP_CXX03_LANG template - _LIBCPP_INLINE_VISIBILITY - pair(piecewise_construct_t, - tuple<_Args1...>& __first_args, tuple<_Args2...>& __second_args, - __tuple_indices<_I1...>, __tuple_indices<_I2...>); + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 + pair(piecewise_construct_t, + tuple<_Args1...>& __first_args, tuple<_Args2...>& __second_args, + __tuple_indices<_I1...>, __tuple_indices<_I2...>); #endif }; @@ -619,7 +619,7 @@ } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 typename enable_if < __is_swappable<_T1>::value && diff --git a/libcxx/include/version b/libcxx/include/version --- a/libcxx/include/version +++ b/libcxx/include/version @@ -41,6 +41,7 @@ __cpp_lib_constexpr_misc 201811L __cpp_lib_constexpr_swap_algorithms 201806L +__cpp_lib_constexpr_utility 201811L __cpp_lib_destroying_delete 201806L __cpp_lib_enable_shared_from_this 201603L __cpp_lib_endian 201907L @@ -223,6 +224,7 @@ // # define __cpp_lib_concepts 201806L // # define __cpp_lib_constexpr_misc 201811L // # define __cpp_lib_constexpr_swap_algorithms 201806L +# define __cpp_lib_constexpr_utility 201811L # if _LIBCPP_STD_VER > 17 && defined(__cpp_impl_destroying_delete) && __cpp_impl_destroying_delete >= 201806L # define __cpp_lib_destroying_delete 201806L # endif diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/utility.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/utility.version.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/utility.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/utility.version.pass.cpp @@ -13,13 +13,14 @@ // Test the feature test macros defined by -/* Constant Value - __cpp_lib_as_const 201510L [C++17] - __cpp_lib_constexpr_misc 201811L [C++2a] - __cpp_lib_exchange_function 201304L [C++14] - __cpp_lib_integer_sequence 201304L [C++14] - __cpp_lib_to_chars 201611L [C++17] - __cpp_lib_tuples_by_type 201304L [C++14] +/* Constant Value + __cpp_lib_as_const 201510L [C++17] + __cpp_lib_constexpr_misc 201811L [C++2a] + __cpp_lib_constexpr_utility 201811L [C++2a] + __cpp_lib_exchange_function 201304L [C++14] + __cpp_lib_integer_sequence 201304L [C++14] + __cpp_lib_to_chars 201611L [C++17] + __cpp_lib_tuples_by_type 201304L [C++14] */ #include @@ -35,6 +36,10 @@ # error "__cpp_lib_constexpr_misc should not be defined before c++2a" # endif +# ifdef __cpp_lib_constexpr_utility +# error "__cpp_lib_constexpr_utility should not be defined before c++2a" +# endif + # ifdef __cpp_lib_exchange_function # error "__cpp_lib_exchange_function should not be defined before c++14" # endif @@ -61,6 +66,10 @@ # error "__cpp_lib_constexpr_misc should not be defined before c++2a" # endif +# ifdef __cpp_lib_constexpr_utility +# error "__cpp_lib_constexpr_utility should not be defined before c++2a" +# endif + # ifndef __cpp_lib_exchange_function # error "__cpp_lib_exchange_function should be defined in c++14" # endif @@ -99,6 +108,10 @@ # error "__cpp_lib_constexpr_misc should not be defined before c++2a" # endif +# ifdef __cpp_lib_constexpr_utility +# error "__cpp_lib_constexpr_utility should not be defined before c++2a" +# endif + # ifndef __cpp_lib_exchange_function # error "__cpp_lib_exchange_function should be defined in c++17" # endif @@ -155,6 +168,13 @@ # endif # endif +# ifndef __cpp_lib_constexpr_utility +# error "__cpp_lib_constexpr_utility should be defined in c++2a" +# endif +# if __cpp_lib_constexpr_utility != 201811L +# error "__cpp_lib_constexpr_utility should have the value 201811L in c++2a" +# endif + # ifndef __cpp_lib_exchange_function # error "__cpp_lib_exchange_function should be defined in c++2a" # endif diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp @@ -35,6 +35,7 @@ __cpp_lib_concepts 201806L [C++2a] __cpp_lib_constexpr_misc 201811L [C++2a] __cpp_lib_constexpr_swap_algorithms 201806L [C++2a] + __cpp_lib_constexpr_utility 201811L [C++2a] __cpp_lib_destroying_delete 201806L [C++2a] __cpp_lib_enable_shared_from_this 201603L [C++17] __cpp_lib_endian 201907L [C++2a] @@ -192,6 +193,10 @@ # error "__cpp_lib_constexpr_swap_algorithms should not be defined before c++2a" # endif +# ifdef __cpp_lib_constexpr_utility +# error "__cpp_lib_constexpr_utility should not be defined before c++2a" +# endif + # ifdef __cpp_lib_destroying_delete # error "__cpp_lib_destroying_delete should not be defined before c++2a" # endif @@ -544,6 +549,10 @@ # error "__cpp_lib_constexpr_swap_algorithms should not be defined before c++2a" # endif +# ifdef __cpp_lib_constexpr_utility +# error "__cpp_lib_constexpr_utility should not be defined before c++2a" +# endif + # ifdef __cpp_lib_destroying_delete # error "__cpp_lib_destroying_delete should not be defined before c++2a" # endif @@ -1010,6 +1019,10 @@ # error "__cpp_lib_constexpr_swap_algorithms should not be defined before c++2a" # endif +# ifdef __cpp_lib_constexpr_utility +# error "__cpp_lib_constexpr_utility should not be defined before c++2a" +# endif + # ifdef __cpp_lib_destroying_delete # error "__cpp_lib_destroying_delete should not be defined before c++2a" # endif @@ -1707,6 +1720,13 @@ # endif # endif +# ifndef __cpp_lib_constexpr_utility +# error "__cpp_lib_constexpr_utility should be defined in c++2a" +# endif +# if __cpp_lib_constexpr_utility != 201811L +# error "__cpp_lib_constexpr_utility should have the value 201811L in c++2a" +# endif + # if TEST_STD_VER > 17 && defined(__cpp_impl_destroying_delete) && __cpp_impl_destroying_delete >= 201806L # ifndef __cpp_lib_destroying_delete # error "__cpp_lib_destroying_delete should be defined in c++2a" diff --git a/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_const_pair_U_V.pass.cpp b/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_const_pair_U_V.pass.cpp --- a/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_const_pair_U_V.pass.cpp +++ b/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_const_pair_U_V.pass.cpp @@ -20,8 +20,7 @@ #include "archetypes.h" #endif -int main(int, char**) -{ +TEST_CONSTEXPR_CXX20 bool test() { { typedef std::pair P1; typedef std::pair P2; @@ -31,7 +30,18 @@ assert(p2.first == 3); assert(p2.second == 4); } -#if TEST_STD_VER >= 11 +#if TEST_STD_VER >= 20 + { + using C = ConstexprTestTypes::TestType; + using P = std::pair; + using T = std::pair; + const T t(42, -42); + P p(101, 101); + p = t; + assert(p.first == 42); + assert(p.second.value == -42); + } +#elif TEST_STD_VER >= 11 { using C = TestTypes::TestType; using P = std::pair; @@ -48,6 +58,15 @@ assert(p.second.value == -42); } #endif + return true; +} + +int main(int, char**) +{ + test(); +#if TEST_STD_VER >= 20 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_pair.pass.cpp b/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_pair.pass.cpp --- a/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_pair.pass.cpp +++ b/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_pair.pass.cpp @@ -19,43 +19,24 @@ #include #include "test_macros.h" - - -struct NonAssignable { - NonAssignable& operator=(NonAssignable const&) = delete; - NonAssignable& operator=(NonAssignable&&) = delete; -}; -struct CopyAssignable { - CopyAssignable() = default; - CopyAssignable(CopyAssignable const&) = default; - CopyAssignable& operator=(CopyAssignable const&) = default; - CopyAssignable& operator=(CopyAssignable&&) = delete; -}; -struct MoveAssignable { - MoveAssignable() = default; - MoveAssignable& operator=(MoveAssignable const&) = delete; - MoveAssignable& operator=(MoveAssignable&&) = default; -}; +#include "archetypes.h" struct CountAssign { - static int copied; - static int moved; - static void reset() { copied = moved = 0; } - CountAssign() = default; - CountAssign& operator=(CountAssign const&) { ++copied; return *this; } - CountAssign& operator=(CountAssign&&) { ++moved; return *this; } + int copied = 0; + int moved = 0; + TEST_CONSTEXPR_CXX20 void reset() { copied = moved = 0; } + TEST_CONSTEXPR_CXX20 CountAssign() = default; + TEST_CONSTEXPR_CXX20 CountAssign& operator=(CountAssign const&) { ++copied; return *this; } + TEST_CONSTEXPR_CXX20 CountAssign& operator=(CountAssign&&) { ++moved; return *this; } }; -int CountAssign::copied = 0; -int CountAssign::moved = 0; struct Incomplete; extern Incomplete inc_obj; -int main(int, char**) -{ +TEST_CONSTEXPR_CXX20 bool test() { { - typedef std::pair P; - const P p1(CopyAssignable(), short{4}); + typedef std::pair P; + const P p1(ConstexprTestTypes::CopyOnly(), short{4}); P p2; p2 = p1; assert(p2.second == 4); @@ -73,21 +54,22 @@ assert(p1.second == y2); } { - using P = std::pair; + using P = std::pair; static_assert(!std::is_copy_assignable

::value, ""); - } + } { - CountAssign::reset(); - using P = std::pair; + using P = std::pair; static_assert(std::is_copy_assignable

::value, ""); P p; P p2; p = p2; - assert(CountAssign::copied == 1); - assert(CountAssign::moved == 0); + assert(p.first.copied == 1); + assert(p.first.moved == 0); + assert(p2.first.copied == 0); + assert(p2.first.moved == 0); } { - using P = std::pair; + using P = std::pair; static_assert(!std::is_copy_assignable

::value, ""); } { @@ -97,7 +79,17 @@ assert(&p.second == &inc_obj); } - return 0; + return true; +} + +int main(int, char**) +{ + test(); +#if TEST_STD_VER >= 20 + static_assert(test()); +#endif + + return 0; } struct Incomplete {}; diff --git a/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_rv_pair.pass.cpp b/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_rv_pair.pass.cpp --- a/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_rv_pair.pass.cpp +++ b/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_rv_pair.pass.cpp @@ -19,42 +19,27 @@ #include #include "test_macros.h" - - -struct NonAssignable { - NonAssignable& operator=(NonAssignable const&) = delete; - NonAssignable& operator=(NonAssignable&&) = delete; -}; -struct CopyAssignable { - CopyAssignable() = default; - CopyAssignable& operator=(CopyAssignable const&) = default; - CopyAssignable& operator=(CopyAssignable&&) = delete; -}; -struct MoveAssignable { - MoveAssignable() = default; - MoveAssignable& operator=(MoveAssignable const&) = delete; - MoveAssignable& operator=(MoveAssignable&&) = default; -}; +#include "archetypes.h" struct CountAssign { - static int copied; - static int moved; - static void reset() { copied = moved = 0; } - CountAssign() = default; - CountAssign& operator=(CountAssign const&) { ++copied; return *this; } - CountAssign& operator=(CountAssign&&) { ++moved; return *this; } + int copied = 0; + int moved = 0; + TEST_CONSTEXPR_CXX20 void reset() { copied = moved = 0; } + TEST_CONSTEXPR_CXX20 CountAssign() = default; + TEST_CONSTEXPR_CXX20 CountAssign& operator=(CountAssign const&) { ++copied; return *this; } + TEST_CONSTEXPR_CXX20 CountAssign& operator=(CountAssign&&) { ++moved; return *this; } }; -int CountAssign::copied = 0; -int CountAssign::moved = 0; -int main(int, char**) -{ +TEST_CONSTEXPR_CXX20 bool test() { +#if TEST_STD_VER >= 20 + if (!std::is_constant_evaluated()) +#endif { - typedef std::pair, int> P; - P p1(std::unique_ptr(new int(3)), 4); + typedef std::pair P; + P p1(3, 4); P p2; p2 = std::move(p1); - assert(*p2.first == 3); + assert(p2.first.value == 3); assert(p2.second == 4); } { @@ -70,30 +55,41 @@ assert(p1.second == y2); } { - using P = std::pair; + using P = std::pair; static_assert(!std::is_move_assignable

::value, ""); } { // The move decays to the copy constructor - CountAssign::reset(); - using P = std::pair; + using P = std::pair; static_assert(std::is_move_assignable

::value, ""); P p; P p2; p = std::move(p2); - assert(CountAssign::moved == 0); - assert(CountAssign::copied == 1); + assert(p.first.moved == 0); + assert(p.first.copied == 1); + assert(p2.first.moved == 0); + assert(p2.first.copied == 0); } { - CountAssign::reset(); - using P = std::pair; + using P = std::pair; static_assert(std::is_move_assignable

::value, ""); P p; P p2; p = std::move(p2); - assert(CountAssign::moved == 1); - assert(CountAssign::copied == 0); + assert(p.first.moved == 1); + assert(p.first.copied == 0); + assert(p2.first.moved == 0); + assert(p2.first.copied == 0); } + return true; +} + +int main(int, char**) +{ + test(); +#if TEST_STD_VER >= 20 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_rv_pair_U_V.pass.cpp b/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_rv_pair_U_V.pass.cpp --- a/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_rv_pair_U_V.pass.cpp +++ b/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_rv_pair_U_V.pass.cpp @@ -17,46 +17,57 @@ #include #include #include -#include #include "test_macros.h" +#include "archetypes.h" -struct Base +struct Derived : ConstexprTestTypes::MoveOnly { - virtual ~Base() {} + Derived() = default; + TEST_CONSTEXPR_CXX20 Derived(ConstexprTestTypes::MoveOnly&&) {}; }; -struct Derived - : public Base -{ -}; - -int main(int, char**) -{ +TEST_CONSTEXPR_CXX20 bool test() { { - typedef std::pair, short> P1; - typedef std::pair, long> P2; - P1 p1(std::unique_ptr(), static_cast(4)); + typedef std::pair P1; + typedef std::pair P2; + P1 p1(Derived(), static_cast(4)); P2 p2; p2 = std::move(p1); - assert(p2.first == nullptr); assert(p2.second == 4); } { +#if TEST_STD_VER >= 20 + using C = ConstexprTestTypes::TestType; +#else using C = TestTypes::TestType; +#endif using P = std::pair; using T = std::pair; T t(42, -42); P p(101, 101); +#if TEST_STD_VER < 20 C::reset_constructors(); +#endif p = std::move(t); +#if TEST_STD_VER < 20 assert(C::constructed == 0); assert(C::assigned == 1); assert(C::copy_assigned == 0); assert(C::move_assigned == 1); +#endif assert(p.first == 42); assert(p.second.value == -42); } + return true; +} + +int main(int, char**) +{ + test(); +#if TEST_STD_VER >= 20 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/utilities/utility/pairs/pairs.pair/const_pair_U_V.pass.cpp b/libcxx/test/std/utilities/utility/pairs/pairs.pair/const_pair_U_V.pass.cpp --- a/libcxx/test/std/utilities/utility/pairs/pairs.pair/const_pair_U_V.pass.cpp +++ b/libcxx/test/std/utilities/utility/pairs/pairs.pair/const_pair_U_V.pass.cpp @@ -25,7 +25,7 @@ template -void test_pair_const() +TEST_CONSTEXPR_CXX20 void test_pair_const() { using P1 = std::pair; using P2 = std::pair; @@ -55,9 +55,8 @@ int value; }; -int main(int, char**) -{ - { +TEST_CONSTEXPR_CXX20 bool test() { + { typedef std::pair P1; typedef std::pair P2; const P1 p1(3, 4); @@ -179,6 +178,15 @@ static_assert(p2.second.value == 101, ""); } #endif + return true; +} + +int main(int, char**) +{ + test(); +#if TEST_STD_VER >= 20 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/utilities/utility/pairs/pairs.pair/piecewise.pass.cpp b/libcxx/test/std/utilities/utility/pairs/pairs.pair/piecewise.pass.cpp --- a/libcxx/test/std/utilities/utility/pairs/pairs.pair/piecewise.pass.cpp +++ b/libcxx/test/std/utilities/utility/pairs/pairs.pair/piecewise.pass.cpp @@ -22,9 +22,7 @@ #include "test_macros.h" - -int main(int, char**) -{ +TEST_CONSTEXPR_CXX20 bool test() { { typedef std::pair P1; typedef std::pair P2; @@ -34,6 +32,15 @@ assert(p3.first == P1(3, nullptr)); assert(p3.second == P2(nullptr, 4)); } + return true; +} + +int main(int, char**) +{ + test(); +#if TEST_STD_VER >= 20 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/utilities/utility/pairs/pairs.pair/swap.pass.cpp b/libcxx/test/std/utilities/utility/pairs/pairs.pair/swap.pass.cpp --- a/libcxx/test/std/utilities/utility/pairs/pairs.pair/swap.pass.cpp +++ b/libcxx/test/std/utilities/utility/pairs/pairs.pair/swap.pass.cpp @@ -19,15 +19,14 @@ struct S { int i; - S() : i(0) {} - S(int j) : i(j) {} + TEST_CONSTEXPR_CXX20 S() : i(0) {} + TEST_CONSTEXPR_CXX20 S(int j) : i(j) {} S * operator& () { assert(false); return this; } S const * operator& () const { assert(false); return this; } - bool operator==(int x) const { return i == x; } - }; + TEST_CONSTEXPR_CXX20 bool operator==(int x) const { return i == x; } +}; -int main(int, char**) -{ +TEST_CONSTEXPR_CXX20 bool test() { { typedef std::pair P1; P1 p1(3, static_cast(4)); @@ -48,6 +47,15 @@ assert(p2.first == 3); assert(p2.second == 4); } + return true; +} + +int main(int, char**) +{ + test(); +#if TEST_STD_VER >= 20 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py --- a/libcxx/utils/generate_feature_test_macro_components.py +++ b/libcxx/utils/generate_feature_test_macro_components.py @@ -598,6 +598,12 @@ }, "headers": ["span"], }, + {"name": "__cpp_lib_constexpr_utility ", + "values": { + "c++2a": int(201811), + }, + "headers": ["utility"], + }, ]], key=lambda tc: tc["name"]) def get_std_dialects():