diff --git a/libcxx/docs/Cxx1zStatusIssuesStatus.csv b/libcxx/docs/Cxx1zStatusIssuesStatus.csv --- a/libcxx/docs/Cxx1zStatusIssuesStatus.csv +++ b/libcxx/docs/Cxx1zStatusIssuesStatus.csv @@ -232,7 +232,7 @@ "`2699 `__","Missing restriction in [numeric.requirements]","Issaquah","|Complete|","" "`2712 `__","copy_file(from, to, ...) has a number of unspecified error conditions","Issaquah","|Complete|","" "`2722 `__","equivalent incorrectly specifies throws clause","Issaquah","|Complete|","" -"`2729 `__","Missing SFINAE on std::pair::operator=","Issaquah","","" +"`2729 `__","Missing SFINAE on std::pair::operator=","Issaquah","|Complete|","" "`2732 `__","Questionable specification of path::operator/= and path::append","Issaquah","|Complete|","" "`2733 `__","[fund.ts.v2] gcd / lcm and bool","Issaquah","|Complete|","" "`2735 `__","std::abs(short), std::abs(signed char) and others should return int instead of double in order to be compatible with C++98 and C","Issaquah","|Complete|","" diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/const_pair.pass.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/const_pair.pass.cpp --- a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/const_pair.pass.cpp +++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/const_pair.pass.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include "test_macros.h" @@ -32,6 +33,13 @@ assert(std::get<0>(t1) == 2); assert(std::get<1>(t1) == short('a')); } + { + // test that the implicitly generated copy assignment operator + // is properly deleted + using T = std::tuple; + using P = std::tuple, std::unique_ptr>; + static_assert(!std::is_assignable::value, ""); + } return 0; } diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/convert_copy.pass.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/convert_copy.pass.cpp --- a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/convert_copy.pass.cpp +++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/convert_copy.pass.cpp @@ -34,6 +34,11 @@ explicit D(int i = 0) : B(i) {} }; +struct NonAssignable { + NonAssignable& operator=(NonAssignable const&) = delete; + NonAssignable& operator=(NonAssignable&&) = delete; +}; + int main(int, char**) { { @@ -87,6 +92,12 @@ assert(std::get<0>(t) == 43); assert(&std::get<0>(t) == &x); } + { + using T = std::tuple; + using U = std::tuple; + static_assert(!std::is_assignable::value, ""); + static_assert(!std::is_assignable::value, ""); + } return 0; } diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/convert_move.pass.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/convert_move.pass.cpp --- a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/convert_move.pass.cpp +++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/convert_move.pass.cpp @@ -45,6 +45,11 @@ } }; +struct NonAssignable { + NonAssignable& operator=(NonAssignable const&) = delete; + NonAssignable& operator=(NonAssignable&&) = delete; +}; + int main(int, char**) { { @@ -108,6 +113,12 @@ assert(std::get<0>(t) == 43); assert(&std::get<0>(t) == &x); } + { + using T = std::tuple; + using U = std::tuple; + static_assert(!std::is_assignable::value, ""); + static_assert(!std::is_assignable::value, ""); + } return 0; } diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/copy.pass.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/copy.pass.cpp --- a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/copy.pass.cpp +++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/copy.pass.cpp @@ -35,6 +35,10 @@ MoveAssignable& operator=(MoveAssignable&&) = default; }; +struct CopyAssignableInt { + CopyAssignableInt& operator=(int&) { return *this; } +}; + int main(int, char**) { { @@ -89,8 +93,9 @@ static_assert(!std::is_copy_assignable::value, ""); } { - using T = std::tuple; - static_assert(!std::is_copy_assignable::value, ""); + // HERE (and below/above) + using T = std::tuple; + static_assert(!std::is_copy_assignable::value, ""); } { using T = std::tuple; @@ -100,6 +105,21 @@ using T = std::tuple; static_assert(!std::is_copy_assignable::value, ""); } + { + using T = std::tuple; + using P = std::pair; + static_assert(!std::is_assignable::value, ""); + } + { // test const requirement + using T = std::tuple; + using P = std::pair; + static_assert(!std::is_assignable::value, ""); + } + { + using T = std::tuple; + using P = std::pair; + static_assert(!std::is_assignable::value, ""); + } return 0; } diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/move.pass.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/move.pass.cpp --- a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/move.pass.cpp +++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/move.pass.cpp @@ -105,8 +105,9 @@ } { - using T = std::tuple; - static_assert(!std::is_move_assignable::value, ""); + // HERE (and below/above) + using T = std::tuple; + static_assert(!std::is_move_assignable::value, ""); } { using T = std::tuple; diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/move_pair.pass.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/move_pair.pass.cpp --- a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/move_pair.pass.cpp +++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/move_pair.pass.cpp @@ -37,6 +37,11 @@ explicit D(int i) : B(i) {} }; +struct NonMoveAssignable { + NonMoveAssignable& operator=(NonMoveAssignable const&) = default; + NonMoveAssignable& operator=(NonMoveAssignable&&) = delete; +}; + int main(int, char**) { { @@ -48,6 +53,16 @@ assert(std::get<0>(t1) == 2); assert(std::get<1>(t1)->id_ == 3); } + { + using T = std::tuple; + using P = std::pair; + static_assert(!std::is_assignable::value, ""); + } + { + using T = std::tuple; + using P = std::pair; + static_assert(!std::is_assignable::value, ""); + } return 0; } 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,6 +20,12 @@ #include "archetypes.h" #endif +struct CopyAssignableInt { + CopyAssignableInt& operator=(int&) { return *this; } +}; + +struct Unrelated {}; + TEST_CONSTEXPR_CXX20 bool test() { { typedef std::pair P1; @@ -58,6 +64,18 @@ assert(p.second.value == -42); } #endif + + { // test const requirement + using T = std::pair; + using P = std::pair; + static_assert(!std::is_assignable::value, ""); + } + { + using T = std::pair; + using P = std::pair; + static_assert(!std::is_assignable::value, ""); + static_assert(!std::is_assignable::value, ""); + } return true; } 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 @@ -77,6 +77,10 @@ using P = std::pair; static_assert(!std::is_copy_assignable

::value, ""); } + { + using P = std::pair >; + static_assert(!std::is_copy_assignable

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

::value, ""); 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 @@ -35,6 +35,11 @@ } }; +struct NotAssignable { + NotAssignable& operator=(NotAssignable const&) = delete; + NotAssignable& operator=(NotAssignable&&) = delete; +}; + TEST_CONSTEXPR_CXX20 bool test() { { typedef std::pair P; @@ -83,6 +88,11 @@ assert(p2.first.moved == 0); assert(p2.first.copied == 0); } + { + using T = std::pair; + using P = std::pair; + static_assert(!std::is_assignable::value, ""); + } return true; } 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 @@ -40,6 +40,10 @@ } }; +struct CopyAssignableInt { + CopyAssignableInt& operator=(int&) { return *this; } +}; + TEST_CONSTEXPR_CXX20 bool test() { { typedef std::pair P1; @@ -61,6 +65,12 @@ assert(t.second.moved == 0); assert(t.second.copied == 0); } + { // test const requirement + using T = std::pair; + using P = std::pair; + static_assert(!std::is_assignable::value, ""); + static_assert(!std::is_assignable::value, ""); + } return true; }