diff --git a/libcxx/include/memory b/libcxx/include/memory --- a/libcxx/include/memory +++ b/libcxx/include/memory @@ -2274,6 +2274,7 @@ _LIBCPP_INLINE_VISIBILITY unique_ptr(pointer __p, _BadRValRefType<_Dummy> __d) = delete; + template::value> > _LIBCPP_INLINE_VISIBILITY unique_ptr(unique_ptr&& __u) _NOEXCEPT : __ptr_(__u.release(), _VSTD::forward(__u.get_deleter())) { @@ -2297,6 +2298,7 @@ : __ptr_(__p.release(), __default_init_tag()) {} #endif + template::value> > _LIBCPP_INLINE_VISIBILITY unique_ptr& operator=(unique_ptr&& __u) _NOEXCEPT { reset(__u.release()); @@ -2327,11 +2329,8 @@ } #endif -#ifdef _LIBCPP_CXX03_LANG unique_ptr(unique_ptr const&) = delete; unique_ptr& operator=(unique_ptr const&) = delete; -#endif - _LIBCPP_INLINE_VISIBILITY ~unique_ptr() { reset(); } @@ -2517,11 +2516,13 @@ _LIBCPP_INLINE_VISIBILITY unique_ptr(_Pp __p, _BadRValRefType<_Dummy> __d) = delete; + template::value> > _LIBCPP_INLINE_VISIBILITY unique_ptr(unique_ptr&& __u) _NOEXCEPT : __ptr_(__u.release(), _VSTD::forward(__u.get_deleter())) { } + template::value> > _LIBCPP_INLINE_VISIBILITY unique_ptr& operator=(unique_ptr&& __u) _NOEXCEPT { reset(__u.release()); @@ -2550,10 +2551,8 @@ return *this; } -#ifdef _LIBCPP_CXX03_LANG unique_ptr(unique_ptr const&) = delete; unique_ptr& operator=(unique_ptr const&) = delete; -#endif public: _LIBCPP_INLINE_VISIBILITY diff --git a/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.asgn/move.pass.cpp b/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.asgn/move.pass.cpp --- a/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.asgn/move.pass.cpp +++ b/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.asgn/move.pass.cpp @@ -74,6 +74,12 @@ assert(A::count == 0); } +template +struct NonMoveableDeleter : std::default_delete { + NonMoveableDeleter() = default; + NonMoveableDeleter& operator=(NonMoveableDeleter&&) = delete; +}; + template void test_sfinae() { typedef typename std::conditional::type VT; @@ -92,22 +98,11 @@ static_assert(std::is_nothrow_assignable::value, ""); } { - typedef std::unique_ptr&> U; - static_assert(!std::is_assignable::value, ""); - static_assert(!std::is_assignable::value, ""); - static_assert(!std::is_assignable::value, ""); - static_assert(std::is_nothrow_assignable::value, ""); - } - { - typedef std::unique_ptr&> U; - static_assert(!std::is_assignable::value, ""); - static_assert(!std::is_assignable::value, ""); - static_assert(!std::is_assignable::value, ""); - static_assert(std::is_nothrow_assignable::value, ""); + typedef std::unique_ptr > NonMoveableUniquePtr; + static_assert(!std::is_move_assignable::value, ""); } } - int main(int, char**) { { test_basic(); diff --git a/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.asgn/move_convert.pass.cpp b/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.asgn/move_convert.pass.cpp --- a/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.asgn/move_convert.pass.cpp +++ b/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.asgn/move_convert.pass.cpp @@ -214,14 +214,9 @@ using U2 = std::unique_ptr >; using U3 = std::unique_ptr &>; using U4 = std::unique_ptr >; - using U5 = std::unique_ptr const&>; static_assert(!std::is_assignable::value, ""); static_assert(!std::is_assignable::value, ""); static_assert(!std::is_assignable::value, ""); - static_assert(!std::is_assignable::value, ""); - - using U1C = std::unique_ptr const&>; - static_assert(std::is_nothrow_assignable::value, ""); } { // Test that if the deleter assignment is not valid the assignment operator // SFINAEs. @@ -295,16 +290,6 @@ typedef std::unique_ptr > BPtr; static_assert(std::is_nothrow_assignable::value, ""); } - { - typedef std::unique_ptr&> APtr; - typedef std::unique_ptr&> BPtr; - static_assert(std::is_nothrow_assignable::value, ""); - } - { - typedef std::unique_ptr&> APtr; - typedef std::unique_ptr&> BPtr; - static_assert(std::is_nothrow_assignable::value, ""); - } } template diff --git a/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.asgn/move_convert.runtime.pass.cpp b/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.asgn/move_convert.runtime.pass.cpp --- a/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.asgn/move_convert.runtime.pass.cpp +++ b/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.asgn/move_convert.runtime.pass.cpp @@ -43,10 +43,14 @@ NCConvertingDeleter() = default; NCConvertingDeleter(NCConvertingDeleter const&) = delete; NCConvertingDeleter(NCConvertingDeleter&&) = default; + NCConvertingDeleter& operator=(NCConvertingDeleter&&) = default; template NCConvertingDeleter(NCConvertingDeleter&&) {} + template + NCConvertingDeleter& operator=(NCConvertingDeleter&&) {} + void operator()(T*) const {} }; @@ -55,10 +59,14 @@ NCConvertingDeleter() = default; NCConvertingDeleter(NCConvertingDeleter const&) = delete; NCConvertingDeleter(NCConvertingDeleter&&) = default; + NCConvertingDeleter& operator=(NCConvertingDeleter&&) = default; template NCConvertingDeleter(NCConvertingDeleter&&) {} + template + NCConvertingDeleter& operator=(NCConvertingDeleter&&) {} + void operator()(T*) const {} }; diff --git a/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.asgn/move_convert.single.pass.cpp b/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.asgn/move_convert.single.pass.cpp --- a/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.asgn/move_convert.single.pass.cpp +++ b/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.asgn/move_convert.single.pass.cpp @@ -44,10 +44,14 @@ NCConvertingDeleter() = default; NCConvertingDeleter(NCConvertingDeleter const&) = delete; NCConvertingDeleter(NCConvertingDeleter&&) = default; + NCConvertingDeleter& operator=(NCConvertingDeleter&&) = default; template NCConvertingDeleter(NCConvertingDeleter&&) {} + template + NCConvertingDeleter& operator=(NCConvertingDeleter&&) {} + void operator()(T*) const {} }; @@ -56,10 +60,14 @@ NCConvertingDeleter() = default; NCConvertingDeleter(NCConvertingDeleter const&) = delete; NCConvertingDeleter(NCConvertingDeleter&&) = default; + NCConvertingDeleter& operator=(NCConvertingDeleter&&) = default; template NCConvertingDeleter(NCConvertingDeleter&&) {} + template + NCConvertingDeleter& operator=(NCConvertingDeleter&&) {} + void operator()(T*) const {} }; diff --git a/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/move.pass.cpp b/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/move.pass.cpp --- a/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/move.pass.cpp +++ b/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/move.pass.cpp @@ -71,13 +71,24 @@ assert(&p.get_deleter() == &source3().get_deleter()); } +template +struct NonMoveableDeleter : std::default_delete { + NonMoveableDeleter() = default; + NonMoveableDeleter& operator=(NonMoveableDeleter&&) = delete; + NonMoveableDeleter(NonMoveableDeleter&&) = delete; +}; + template void test_sfinae() { - typedef std::unique_ptr U; { // Ensure unique_ptr is non-copyable + typedef std::unique_ptr U; static_assert((!std::is_constructible::value), ""); static_assert((!std::is_constructible::value), ""); } + { + typedef std::unique_ptr > NonMoveableUniquePtr; + static_assert(!std::is_move_constructible::value, ""); + } } template diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/move.pass.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/move.pass.cpp --- a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/move.pass.cpp +++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/move.pass.cpp @@ -48,6 +48,12 @@ int value; }; +// is_move_constructible_v = false here +struct no_move_const { + no_move_const(no_move_const const&) = delete; + no_move_const(no_move_const&&) = delete; +}; + template void test_sfinae() { using Tup = std::tuple; @@ -110,6 +116,19 @@ assert(std::get<1>(t) == 1); assert(std::get<2>(t) == 2); } + // Issue 2899: + // Constraints: is_move_constructible_v is true for all i. + { + typedef std::tuple T1; + typedef std::tuple T2; + typedef std::tuple T3; + typedef std::tuple T4; + + static_assert(!std::is_move_constructible::value, ""); + static_assert(!std::is_move_constructible::value, ""); + static_assert(!std::is_move_constructible::value, ""); + static_assert(!std::is_move_constructible::value, ""); + } // A bug in tuple caused __tuple_leaf to use its explicit converting constructor // as its move constructor. This tests that ConstructsWithTupleLeaf is not called // (w/ __tuple_leaf) diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.elem/tuple.by.type.fail.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.elem/tuple.by.type.fail.cpp --- a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.elem/tuple.by.type.fail.cpp +++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.elem/tuple.by.type.fail.cpp @@ -28,7 +28,7 @@ void test_bad_return_type() { typedef std::unique_ptr upint; std::tuple t; - upint p = std::get(t); // expected-error{{deleted copy constructor}} + upint p = std::get(t); // expected-error{{call to deleted constructor of 'upint' (aka 'unique_ptr')}} } int main(int, char**) diff --git a/libcxx/test/support/deleter_types.h b/libcxx/test/support/deleter_types.h --- a/libcxx/test/support/deleter_types.h +++ b/libcxx/test/support/deleter_types.h @@ -223,6 +223,7 @@ public: NCDeleter() : state_(0) {} + NCDeleter& operator=(NCDeleter&& other) { return NCDeleter(std::move(other.state_)); } explicit NCDeleter(int s) : state_(s) {} ~NCDeleter() {assert(state_ >= 0); state_ = -1;} @@ -242,6 +243,7 @@ public: NCDeleter() : state_(0) {} + NCDeleter& operator=(NCDeleter&& other) { return NCDeleter(std::move(other.state_)); } explicit NCDeleter(int s) : state_(s) {} ~NCDeleter() {assert(state_ >= 0); state_ = -1;} @@ -263,6 +265,11 @@ NCConstDeleter() : state_(0) {} explicit NCConstDeleter(int s) : state_(s) {} + NCConstDeleter& operator=(NCConstDeleter&& other) + { + return NCConstDeleter(std::move(other.state_)); + } + ~NCConstDeleter() {assert(state_ >= 0); state_ = -1;} int state() const {return state_;} @@ -282,6 +289,11 @@ NCConstDeleter() : state_(0) {} explicit NCConstDeleter(int s) : state_(s) {} + NCConstDeleter& operator=(NCConstDeleter&& other) + { + return NCConstDeleter(std::move(other.state_)); + } + ~NCConstDeleter() {assert(state_ >= 0); state_ = -1;} int state() const {return state_;} diff --git a/libcxx/www/cxx2a_status.html b/libcxx/www/cxx2a_status.html --- a/libcxx/www/cxx2a_status.html +++ b/libcxx/www/cxx2a_status.html @@ -420,7 +420,7 @@ 3182Specification of Same could be clearerKona - 2899is_(nothrow_)move_constructible and tuple, optional and unique_ptrCologne + 2899is_(nothrow_)move_constructible and tuple, optional and unique_ptrCologneComplete 3055path::operator+=(single-character) misspecifiedCologne 3158tuple(allocator_arg_t, const Alloc&) should be conditionally explicitCologne 3169ranges permutation generators discard useful informationCologne