Author: ericwf Date: Fri Oct 7 16:27:45 2016 New Revision: 283606 URL: http://llvm.org/viewvc/llvm-project?rev=283606&view=rev Log: Fix various issues in std::any and the related tests.
* Fix self-swap. Patch from Casey Carter. * Remove workarounds and tests for types with deleted move constructors. This was originally added as part of a LWG proposed resolution that has since changed. * Re-apply most recent PR for LWG 2769. * Re-apply most recent PR for LWG 2754. Specifically fix the SFINAE checks to use the decayed type. * Fix tests to allow moved-from std::any's to have a non-empty state. This is the behavior of MSVC's std::any. * Various whitespace and test fixes. Added: libcxx/trunk/test/std/utilities/any/any.nonmembers/any.cast/rvalue_any_cast_request_lvalue.fail.cpp Modified: libcxx/trunk/include/any libcxx/trunk/include/type_traits libcxx/trunk/test/std/utilities/any/any.class/any.assign/move.pass.cpp libcxx/trunk/test/std/utilities/any/any.class/any.assign/value.pass.cpp libcxx/trunk/test/std/utilities/any/any.class/any.cons/copy.pass.cpp libcxx/trunk/test/std/utilities/any/any.class/any.cons/in_place_type.pass.cpp libcxx/trunk/test/std/utilities/any/any.class/any.cons/move.pass.cpp libcxx/trunk/test/std/utilities/any/any.class/any.cons/value.pass.cpp libcxx/trunk/test/std/utilities/any/any.class/any.modifiers/emplace.pass.cpp libcxx/trunk/test/std/utilities/any/any.class/any.modifiers/swap.pass.cpp libcxx/trunk/test/std/utilities/any/any.nonmembers/any.cast/any_cast_reference.pass.cpp libcxx/trunk/test/std/utilities/any/any.nonmembers/any.cast/const_correctness.fail.cpp libcxx/trunk/test/std/utilities/any/any.nonmembers/any.cast/not_copy_constructible.fail.cpp libcxx/trunk/test/std/utilities/any/any.nonmembers/make_any.pass.cpp libcxx/trunk/test/support/any_helpers.h libcxx/trunk/test/support/test_macros.h Modified: libcxx/trunk/include/any URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/any?rev=283606&r1=283605&r2=283606&view=diff ============================================================================== --- libcxx/trunk/include/any (original) +++ libcxx/trunk/include/any Fri Oct 7 16:27:45 2016 @@ -197,30 +197,33 @@ public: template < class _ValueType + , class _Tp = decay_t<_ValueType> , class = enable_if_t< - !is_same<decay_t<_ValueType>, any>::value && + !is_same<_Tp, any>::value && !__is_inplace_type<_ValueType>::value && - is_copy_constructible<_ValueType>::value> + is_copy_constructible<_Tp>::value> > _LIBCPP_INLINE_VISIBILITY any(_ValueType && __value); - template <class _Tp, class ..._Args, + template <class _ValueType, class ..._Args, + class _Tp = decay_t<_ValueType>, class = enable_if_t< is_constructible<_Tp, _Args...>::value && is_copy_constructible<_Tp>::value > > _LIBCPP_INLINE_VISIBILITY - explicit any(in_place_type_t<_Tp>, _Args&&... __args); + explicit any(in_place_type_t<_ValueType>, _Args&&... __args); - template <class _Tp, class _Up, class ..._Args, + template <class _ValueType, class _Up, class ..._Args, + class _Tp = decay_t<_ValueType>, class = enable_if_t< is_constructible<_Tp, initializer_list<_Up>&, _Args...>::value && is_copy_constructible<_Tp>::value> > _LIBCPP_INLINE_VISIBILITY - explicit any(in_place_type_t<_Tp>, initializer_list<_Up>, _Args&&... __args); + explicit any(in_place_type_t<_ValueType>, initializer_list<_Up>, _Args&&... __args); _LIBCPP_INLINE_VISIBILITY ~any() { this->reset(); } @@ -242,15 +245,17 @@ public: // ValueType constructor? template < class _ValueType + , class _Tp = decay_t<_ValueType> , class = enable_if_t< - !is_same<decay_t<_ValueType>, any>::value - && is_copy_constructible<_ValueType>::value + !is_same<_Tp, any>::value + && is_copy_constructible<_Tp>::value && !__is_inplace_type<_ValueType>::value> > _LIBCPP_INLINE_VISIBILITY any & operator=(_ValueType && __rhs); - template <class _Tp, class ..._Args, + template <class _ValueType, class ..._Args, + class _Tp = decay_t<_ValueType>, class = enable_if_t< is_constructible<_Tp, _Args...>::value && is_copy_constructible<_Tp>::value> @@ -258,7 +263,8 @@ public: _LIBCPP_INLINE_VISIBILITY void emplace(_Args&&... args); - template <class _Tp, class _Up, class ..._Args, + template <class _ValueType, class _Up, class ..._Args, + class _Tp = decay_t<_ValueType>, class = enable_if_t< is_constructible<_Tp, initializer_list<_Up>&, _Args...>::value && is_copy_constructible<_Tp>::value> @@ -490,60 +496,49 @@ namespace __any_imp } // namespace __any_imp -template <class _ValueType, class> +template <class _ValueType, class _Tp, class> any::any(_ValueType && __v) : __h(nullptr) { - typedef typename decay<_ValueType>::type _Tp; - static_assert(is_copy_constructible<_Tp>::value, - "_ValueType must be CopyConstructible."); - using _ForwardTp = conditional_t< - is_move_constructible<_Tp>::value, _ValueType, _ValueType&>; - typedef __any_imp::_Handler<_Tp> _HandlerType; - _HandlerType::__create(*this, _VSTD::forward<_ForwardTp>(__v)); + __any_imp::_Handler<_Tp>::__create(*this, _VSTD::forward<_ValueType>(__v)); } -template <class _Tp, class ..._Args, class> -any::any(in_place_type_t<_Tp>, _Args&&... __args) { - using _Hp = __any_imp::_Handler<_Tp>; - _Hp::__create(*this, _VSTD::forward<_Args>(__args)...); +template <class _ValueType, class ..._Args, class _Tp, class> +any::any(in_place_type_t<_ValueType>, _Args&&... __args) { + __any_imp::_Handler<_Tp>::__create(*this, _VSTD::forward<_Args>(__args)...); }; -template <class _Tp, class _Up, class ..._Args, class> -any::any(in_place_type_t<_Tp>, initializer_list<_Up> __il, _Args&&... __args) { - using _Hp = __any_imp::_Handler<_Tp>; - _Hp::__create(*this, __il, _VSTD::forward<_Args>(__args)...); +template <class _ValueType, class _Up, class ..._Args, class _Tp, class> +any::any(in_place_type_t<_ValueType>, initializer_list<_Up> __il, _Args&&... __args) { + __any_imp::_Handler<_Tp>::__create(*this, __il, _VSTD::forward<_Args>(__args)...); } -template <class _ValueType, class> +template <class _ValueType, class, class> inline _LIBCPP_INLINE_VISIBILITY any & any::operator=(_ValueType && __v) { - typedef typename decay<_ValueType>::type _Tp; - static_assert(is_copy_constructible<_Tp>::value, - "_ValueType must be CopyConstructible."); any(_VSTD::forward<_ValueType>(__v)).swap(*this); return *this; } -template <class _Tp, class ..._Args, class> +template <class _ValueType, class ..._Args, class _Tp, class> inline _LIBCPP_INLINE_VISIBILITY void any::emplace(_Args&&... __args) { - using _Hp = __any_imp::_Handler<_Tp>; reset(); - _Hp::__create(*this, _VSTD::forward<_Args>(__args)...); + __any_imp::_Handler<_Tp>::__create(*this, _VSTD::forward<_Args>(__args)...); } -template <class _Tp, class _Up, class ..._Args, class> +template <class _ValueType, class _Up, class ..._Args, class _Tp, class> inline _LIBCPP_INLINE_VISIBILITY void any::emplace(initializer_list<_Up> __il, _Args&&... __args) { - using _Hp = __any_imp::_Handler<_Tp>; reset(); - _Hp::__create(*this, __il, _VSTD::forward<_Args>(__args)...); + __any_imp::_Handler<_Tp>::__create(*this, __il, _VSTD::forward<_Args>(__args)...); } inline _LIBCPP_INLINE_VISIBILITY void any::swap(any & __rhs) _NOEXCEPT { + if (this == &__rhs) + return; if (__h && __rhs.__h) { any __tmp; __rhs.__call(_Action::_Move, &__tmp); @@ -582,50 +577,39 @@ template <class _ValueType> inline _LIBCPP_INLINE_VISIBILITY _ValueType any_cast(any const & __v) { - static_assert( - is_reference<_ValueType>::value - || is_copy_constructible<_ValueType>::value, - "_ValueType is required to be a reference or a CopyConstructible type."); - using _Tp = add_const_t<remove_reference_t<_ValueType>>; - _Tp * __tmp = _VSTD::any_cast<_Tp>(&__v); + using _RawValueType = __uncvref_t<_ValueType>; + static_assert(is_constructible<_ValueType, _RawValueType const &>::value, + "ValueType is required to be a reference or a CopyConstructible type"); + auto __tmp = _VSTD::any_cast<add_const_t<_RawValueType>>(&__v); if (__tmp == nullptr) __throw_bad_any_cast(); - return *__tmp; + return static_cast<_ValueType>(*__tmp); } template <class _ValueType> inline _LIBCPP_INLINE_VISIBILITY _ValueType any_cast(any & __v) { - static_assert( - is_reference<_ValueType>::value - || is_copy_constructible<_ValueType>::value, - "_ValueType is required to be a reference or a CopyConstructible type."); - typedef typename remove_reference<_ValueType>::type _Tp; - _Tp * __tmp = _VSTD::any_cast<_Tp>(&__v); + using _RawValueType = __uncvref_t<_ValueType>; + static_assert(is_constructible<_ValueType, _RawValueType &>::value, + "ValueType is required to be a reference or a CopyConstructible type"); + auto __tmp = _VSTD::any_cast<_RawValueType>(&__v); if (__tmp == nullptr) __throw_bad_any_cast(); - return *__tmp; + return static_cast<_ValueType>(*__tmp); } template <class _ValueType> inline _LIBCPP_INLINE_VISIBILITY _ValueType any_cast(any && __v) { - static_assert( - is_reference<_ValueType>::value - || is_copy_constructible<_ValueType>::value, - "_ValueType is required to be a reference or a CopyConstructible type."); - typedef typename remove_reference<_ValueType>::type _Tp; - using _ForwardTp = conditional_t< - is_reference<_ValueType>::value, - _ValueType, - conditional_t<is_move_constructible<_Tp>::value, _Tp, _Tp&> - >; - _Tp * __tmp = _VSTD::any_cast<_Tp>(&__v); + using _RawValueType = __uncvref_t<_ValueType>; + static_assert(is_constructible<_ValueType, _RawValueType>::value, + "ValueType is required to be an rvalue reference or a CopyConstructible type"); + auto __tmp = _VSTD::any_cast<_RawValueType>(&__v); if (__tmp == nullptr) __throw_bad_any_cast(); - return _VSTD::forward<_ForwardTp>(*__tmp); + return static_cast<_ValueType>(_VSTD::move(*__tmp)); } template <class _ValueType> Modified: libcxx/trunk/include/type_traits URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/type_traits?rev=283606&r1=283605&r2=283606&view=diff ============================================================================== --- libcxx/trunk/include/type_traits (original) +++ libcxx/trunk/include/type_traits Fri Oct 7 16:27:45 2016 @@ -1122,6 +1122,11 @@ struct __unconstref { typedef typename remove_const<typename remove_reference<_Tp>::type>::type type; }; +#ifndef _LIBCPP_CXX03_LANG +template <class _Tp> +using __uncvref_t = typename __uncvref<_Tp>::type; +#endif + // __is_same_uncvref template <class _Tp, class _Up> Modified: libcxx/trunk/test/std/utilities/any/any.class/any.assign/move.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/any/any.class/any.assign/move.pass.cpp?rev=283606&r1=283605&r2=283606&view=diff ============================================================================== --- libcxx/trunk/test/std/utilities/any/any.class/any.assign/move.pass.cpp (original) +++ libcxx/trunk/test/std/utilities/any/any.class/any.assign/move.pass.cpp Fri Oct 7 16:27:45 2016 @@ -40,10 +40,13 @@ void test_move_assign() { a = std::move(a2); assert(LHS::count == 1); - assert(RHS::count == 2); + assert(RHS::count == 2 + a2.has_value()); + LIBCPP_ASSERT(RHS::count == 2); // libc++ leaves the object empty assertContains<RHS>(a, 2); - assertEmpty<RHS>(a2); + if (a2.has_value()) + assertContains<RHS>(a2, 0); + LIBCPP_ASSERT(!a2.has_value()); } assert(LHS::count == 0); assert(RHS::count == 0); @@ -54,16 +57,19 @@ void test_move_assign_empty() { assert(LHS::count == 0); { any a; - any a2((LHS(1))); + any a2((LHS(1))); assert(LHS::count == 1); a = std::move(a2); - assert(LHS::count == 1); + assert(LHS::count == 1 + a2.has_value()); + LIBCPP_ASSERT(LHS::count == 1); assertContains<LHS>(a, 1); - assertEmpty<LHS>(a2); + if (a2.has_value()) + assertContains<LHS>(a2, 0); + LIBCPP_ASSERT(!a2.has_value()); } assert(LHS::count == 0); { Modified: libcxx/trunk/test/std/utilities/any/any.class/any.assign/value.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/any/any.class/any.assign/value.pass.cpp?rev=283606&r1=283605&r2=283606&view=diff ============================================================================== --- libcxx/trunk/test/std/utilities/any/any.class/any.assign/value.pass.cpp (original) +++ libcxx/trunk/test/std/utilities/any/any.class/any.assign/value.pass.cpp Fri Oct 7 16:27:45 2016 @@ -11,7 +11,8 @@ // <any> -// any& operator=(any const &); +// template <class ValueType> +// any& operator=(ValueType&&); // Test value copy and move assignment. @@ -65,10 +66,12 @@ void test_assign_value() { assert(RHS::moved >= 1); assert(RHS::copied == 0); assert(LHS::count == 0); - assert(RHS::count == 1); + assert(RHS::count == 1 + rhs.has_value()); + LIBCPP_ASSERT(!rhs.has_value()); assertContains<RHS>(lhs, 2); - assertEmpty<RHS>(rhs); + if (rhs.has_value()) + assertContains<RHS>(rhs, 0); } assert(LHS::count == 0); assert(RHS::count == 0); @@ -114,7 +117,7 @@ void test_assign_value_empty() { template <class Tp, bool Move = false> void test_assign_throws() { #if !defined(TEST_HAS_NO_EXCEPTIONS) - auto try_throw= + auto try_throw = [](any& lhs, auto&& rhs) { try { Move ? lhs = std::move(rhs) @@ -188,6 +191,7 @@ void test_sfinae_constraints() { NoCopy(NoCopy&&) = default; }; static_assert(!std::is_assignable<std::any, NoCopy>::value, ""); + static_assert(!std::is_assignable<std::any, NoCopy&>::value, ""); } } @@ -202,4 +206,4 @@ int main() { test_assign_throws<large_throws_on_copy>(); test_assign_throws<throws_on_move, /* Move = */ true>(); test_sfinae_constraints(); -} \ No newline at end of file +} Modified: libcxx/trunk/test/std/utilities/any/any.class/any.cons/copy.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/any/any.class/any.cons/copy.pass.cpp?rev=283606&r1=283605&r2=283606&view=diff ============================================================================== --- libcxx/trunk/test/std/utilities/any/any.class/any.cons/copy.pass.cpp (original) +++ libcxx/trunk/test/std/utilities/any/any.class/any.cons/copy.pass.cpp Fri Oct 7 16:27:45 2016 @@ -71,7 +71,7 @@ void test_copy() assert(Type::copied == 1); assert(Type::count == 2); assertContains<Type>(a, 42); - assertContains<Type>(a, 42); + assertContains<Type>(a2, 42); // Modify a and check that a2 is unchanged modifyValue<Type>(a, -1); Modified: libcxx/trunk/test/std/utilities/any/any.class/any.cons/in_place_type.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/any/any.class/any.cons/in_place_type.pass.cpp?rev=283606&r1=283605&r2=283606&view=diff ============================================================================== --- libcxx/trunk/test/std/utilities/any/any.class/any.cons/in_place_type.pass.cpp (original) +++ libcxx/trunk/test/std/utilities/any/any.class/any.cons/in_place_type.pass.cpp Fri Oct 7 16:27:45 2016 @@ -49,6 +49,16 @@ void test_in_place_type() { } assert(Type::count == 0); Type::reset(); + { // Test that the in_place argument is properly decayed + any a(std::in_place<Type&>); + + assert(Type::count == 1); + assert(Type::copied == 0); + assert(Type::moved == 0); + assertContains<Type>(a, 0); + } + assert(Type::count == 0); + Type::reset(); { any a(std::in_place<Type>, 101); @@ -90,11 +100,38 @@ void test_in_place_type_tracked() { } { int x = 42; - any a(std::in_place<Type>, {-1, 42, -1}, x); + any a(std::in_place<Type&>, {-1, 42, -1}, x); assertArgsMatch<Type, std::initializer_list<int>, int&>(a); } } +void test_func() {} + +void test_in_place_type_decayed() { + { + using Type = decltype(test_func); + using DecayT = void(*)(); + any a(std::in_place<Type>, test_func); + assert(containsType<DecayT>(a)); + assert(any_cast<DecayT>(a) == test_func); + } + { + int my_arr[5]; + using Type = int(&)[5]; + using DecayT = int*; + any a(std::in_place<Type>, my_arr); + assert(containsType<DecayT>(a)); + assert(any_cast<DecayT>(a) == my_arr); + } + { + using Type = int[5]; + using DecayT = int*; + any a(std::in_place<Type>); + assert(containsType<DecayT>(a)); + assert(any_cast<DecayT>(a) == nullptr); + } +} + void test_ctor_sfinae() { { // Test that the init-list ctor SFINAE's away properly when @@ -115,10 +152,14 @@ void test_ctor_sfinae() { NoCopy(std::initializer_list<int>, int) {} }; using Tag = std::in_place_type_t<NoCopy>; + using RefTag = std::in_place_type_t<NoCopy&>; using IL = std::initializer_list<int>; static_assert(!std::is_constructible<std::any, Tag>::value, ""); static_assert(!std::is_constructible<std::any, Tag, int>::value, ""); static_assert(!std::is_constructible<std::any, Tag, IL, int>::value, ""); + static_assert(!std::is_constructible<std::any, RefTag>::value, ""); + static_assert(!std::is_constructible<std::any, RefTag, int>::value, ""); + static_assert(!std::is_constructible<std::any, RefTag, IL, int>::value, ""); } } @@ -147,6 +188,7 @@ int main() { test_in_place_type<throws_on_move>(); test_in_place_type_tracked<small_tracked_t>(); test_in_place_type_tracked<large_tracked_t>(); + test_in_place_type_decayed(); test_ctor_sfinae(); test_constructor_explicit(); -} \ No newline at end of file +} Modified: libcxx/trunk/test/std/utilities/any/any.class/any.cons/move.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/any/any.class/any.cons/move.pass.cpp?rev=283606&r1=283605&r2=283606&view=diff ============================================================================== --- libcxx/trunk/test/std/utilities/any/any.class/any.cons/move.pass.cpp (original) +++ libcxx/trunk/test/std/utilities/any/any.class/any.cons/move.pass.cpp Fri Oct 7 16:27:45 2016 @@ -77,11 +77,13 @@ void test_move() { any a2(std::move(a)); - assert(Type::moved >= 1); // zero or more move operations can be performed. + assert(Type::moved == 1 || Type::moved == 2); // zero or more move operations can be performed. assert(Type::copied == 0); // no copies can be performed. - assert(Type::count == 1); + assert(Type::count == 1 + a.has_value()); assertEmpty(a); // Moves are always destructive. assertContains<Type>(a2, 42); + if (a.has_value()) + assertContains<Type>(a, 0); } assert(Type::count == 0); } Modified: libcxx/trunk/test/std/utilities/any/any.class/any.cons/value.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/any/any.class/any.cons/value.pass.cpp?rev=283606&r1=283605&r2=283606&view=diff ============================================================================== --- libcxx/trunk/test/std/utilities/any/any.class/any.cons/value.pass.cpp (original) +++ libcxx/trunk/test/std/utilities/any/any.class/any.cons/value.pass.cpp Fri Oct 7 16:27:45 2016 @@ -30,7 +30,6 @@ using std::any; using std::any_cast; - template <class Type> void test_copy_value_throws() { @@ -107,33 +106,6 @@ void test_copy_move_value() { } } -void test_non_moveable_type() -{ - using Type = deleted_move; - { - deleted_move mv(42); - std::any a(mv); - assert(Type::count == 2); - assert(Type::copied == 1); - assert(Type::moved == 0); - assertContains<Type>(a, 42); - } - assert(Type::count == 0); - Type::reset(); - { - deleted_move mv(42); - std::any a(std::move(mv)); - assert(Type::count == 2); - assert(Type::copied == 1); - assert(Type::moved == 0); - assertContains<Type>(a, 42); - } - assert(Type::count == 0); - Type::reset(); -} - - - // Test that any(ValueType&&) is *never* selected for a std::in_place type. void test_sfinae_constraints() { using Tag = std::in_place_type_t<int>; @@ -169,6 +141,7 @@ void test_sfinae_constraints() { NoCopy(int) {} }; static_assert(!std::is_constructible<std::any, NoCopy>::value, ""); + static_assert(!std::is_constructible<std::any, NoCopy&>::value, ""); static_assert(!std::is_convertible<NoCopy, std::any>::value, ""); } } @@ -179,6 +152,5 @@ int main() { test_copy_value_throws<small_throws_on_copy>(); test_copy_value_throws<large_throws_on_copy>(); test_move_value_throws(); - test_non_moveable_type(); test_sfinae_constraints(); } \ No newline at end of file Modified: libcxx/trunk/test/std/utilities/any/any.class/any.modifiers/emplace.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/any/any.class/any.modifiers/emplace.pass.cpp?rev=283606&r1=283605&r2=283606&view=diff ============================================================================== --- libcxx/trunk/test/std/utilities/any/any.class/any.modifiers/emplace.pass.cpp (original) +++ libcxx/trunk/test/std/utilities/any/any.class/any.modifiers/emplace.pass.cpp Fri Oct 7 16:27:45 2016 @@ -129,7 +129,7 @@ static_assert(IsSmallObject<SmallThrows> struct LargeThrows { LargeThrows(int) { throw 42; } LargeThrows(std::initializer_list<int>, int) { throw 42; } - int data[10]; + int data[sizeof(std::any)]; }; static_assert(!IsSmallObject<LargeThrows>::value, ""); @@ -236,6 +236,13 @@ void test_emplace_sfinae_constraints() { static_assert(!has_emplace<NoCopy>(), ""); static_assert(!has_emplace<NoCopy, int>(), ""); static_assert(!has_emplace_init_list<NoCopy, int, int, int>(), ""); + static_assert(!has_emplace<NoCopy&>(), ""); + static_assert(!has_emplace<NoCopy&, int>(), ""); + static_assert(!has_emplace_init_list<NoCopy&, int, int, int>(), ""); + static_assert(!has_emplace<NoCopy&&>(), ""); + static_assert(!has_emplace<NoCopy&&, int>(), ""); + static_assert(!has_emplace_init_list<NoCopy&&, int, int, int>(), ""); + } } @@ -252,4 +259,4 @@ int main() { test_emplace_throws<SmallThrows>(); test_emplace_throws<LargeThrows>(); #endif -} \ No newline at end of file +} Modified: libcxx/trunk/test/std/utilities/any/any.class/any.modifiers/swap.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/any/any.class/any.modifiers/swap.pass.cpp?rev=283606&r1=283605&r2=283606&view=diff ============================================================================== --- libcxx/trunk/test/std/utilities/any/any.class/any.modifiers/swap.pass.cpp (original) +++ libcxx/trunk/test/std/utilities/any/any.class/any.modifiers/swap.pass.cpp Fri Oct 7 16:27:45 2016 @@ -89,6 +89,37 @@ void test_noexcept() ); } +void test_self_swap() { + { + // empty + any a; + a.swap(a); + assertEmpty(a); + } + { // small + using T = small; + any a{T{42}}; + T::reset(); + a.swap(a); + assertContains<T>(a, 42); + assert(T::count == 1); + assert(T::copied == 0); + assert(T::moved == 0); + } + assert(small::count == 0); + { // large + using T = large; + any a{T{42}}; + T::reset(); + a.swap(a); + assertContains<T>(a, 42); + assert(T::copied == 0); + assert(T::moved == 0); + assert(T::count == 1); + } + assert(large::count == 0); +} + int main() { test_noexcept(); @@ -98,4 +129,5 @@ int main() test_swap<large1, large2>(); test_swap<small, large>(); test_swap<large, small>(); + test_self_swap(); } Modified: libcxx/trunk/test/std/utilities/any/any.nonmembers/any.cast/any_cast_reference.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/any/any.nonmembers/any.cast/any_cast_reference.pass.cpp?rev=283606&r1=283605&r2=283606&view=diff ============================================================================== --- libcxx/trunk/test/std/utilities/any/any.nonmembers/any.cast/any_cast_reference.pass.cpp (original) +++ libcxx/trunk/test/std/utilities/any/any.nonmembers/any.cast/any_cast_reference.pass.cpp Fri Oct 7 16:27:45 2016 @@ -91,7 +91,12 @@ void checkThrows(any& a) } try { - any_cast<Type>(static_cast<any&&>(a)); + using RefType = typename std::conditional< + std::is_lvalue_reference<Type>::value, + typename std::remove_reference<Type>::type&&, + Type + >::type; + any_cast<RefType>(static_cast<any&&>(a)); assert(false); } catch (bad_any_cast const &) { // do nothing @@ -142,14 +147,6 @@ void test_cast_to_reference() { Type const &cv = any_cast<Type const&>(ca); assert(&cv == &v); } - // Check getting a type by reference from a non-const rvalue - { - Type& v = any_cast<Type&>(std::move(a)); - assert(v.value == 42); - - Type const &cv = any_cast<Type const&>(std::move(a)); - assert(&cv == &v); - } // Check getting a type by reference from a const rvalue any. { Type const& v = any_cast<Type const&>(std::move(ca)); @@ -229,8 +226,8 @@ void test_cast_to_value() { assert(Type::count == 2); assert(Type::copied == 1); - assert(Type::const_copied == 1); - assert(Type::non_const_copied == 0); + assert(Type::const_copied == 0); + assert(Type::non_const_copied == 1); assert(Type::moved == 0); assert(t.value == 42); } @@ -272,12 +269,13 @@ void test_cast_to_value() { Type t = any_cast<Type const>(static_cast<any &&>(a)); assert(Type::count == 2); - assert(Type::copied == 1); - assert(Type::const_copied == 1); + assert(Type::copied == 0); + assert(Type::const_copied == 0); assert(Type::non_const_copied == 0); - assert(Type::moved == 0); + assert(Type::moved == 1); assert(t.value == 42); - assert(any_cast<Type&>(a).value == 42); + assert(any_cast<Type&>(a).value == 0); + any_cast<Type&>(a).value = 42; // reset the value } assert(Type::count == 1); Type::reset(); @@ -303,86 +301,6 @@ void test_cast_to_value() { assert(Type::count == 0); } -void test_cast_to_value_deleted_move() -{ - using Type = deleted_move; - { - std::any a(deleted_move(42)); - assert(Type::count == 1); - assert(Type::copied == 1); - assert(Type::moved == 0); - - Type const& t = any_cast<Type>(a); - assert(Type::count == 2); - assert(Type::copied == 2); - assert(Type::moved == 0); - assertContains<Type>(a, 42); - } - assert(Type::count == 0); - Type::reset(); - { - std::any a(deleted_move(42)); - std::any const& ca = a; - assert(Type::count == 1); - assert(Type::copied == 1); - assert(Type::moved == 0); - - Type const& t = any_cast<Type>(ca); - assert(Type::count == 2); - assert(Type::copied == 2); - assert(Type::moved == 0); - assertContains<Type>(a, 42); - } - assert(Type::count == 0); - Type::reset(); - { - std::any a(deleted_move(42)); - assert(Type::count == 1); - assert(Type::copied == 1); - assert(Type::moved == 0); - - Type&& t = any_cast<Type>(std::move(a)); - assert(Type::count == 2); - assert(Type::copied == 2); - assert(Type::moved == 0); - assertContains<Type>(a, 42); - } - assert(Type::count == 0); - Type::reset(); - { - std::any a(deleted_move(42)); - std::any const& ca = a; - assert(Type::count == 1); - assert(Type::copied == 1); - assert(Type::moved == 0); - - Type&& t = any_cast<Type>(std::move(ca)); - assert(Type::count == 2); - assert(Type::copied == 2); - assert(Type::moved == 0); - assertContains<Type>(a, 42); - } - assert(Type::count == 0); - Type::reset(); -} - -// Even though you can't get a non-copyable class into std::any -// the standard requires that these overloads compile and function. -void test_non_copyable_ref() { - struct no_copy - { - no_copy() {} - no_copy(no_copy &&) {} - private: - no_copy(no_copy const &); - }; - - any a; - checkThrows<no_copy &, no_copy const&>(a); - checkThrows<no_copy const&>(a); - assertEmpty(a); -} - int main() { test_cast_is_not_noexcept(); test_cast_return_type(); @@ -391,6 +309,4 @@ int main() { test_cast_to_reference<large>(); test_cast_to_value<small>(); test_cast_to_value<large>(); - test_cast_to_value_deleted_move(); - test_non_copyable_ref(); } Modified: libcxx/trunk/test/std/utilities/any/any.nonmembers/any.cast/const_correctness.fail.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/any/any.nonmembers/any.cast/const_correctness.fail.cpp?rev=283606&r1=283605&r2=283606&view=diff ============================================================================== --- libcxx/trunk/test/std/utilities/any/any.nonmembers/any.cast/const_correctness.fail.cpp (original) +++ libcxx/trunk/test/std/utilities/any/any.nonmembers/any.cast/const_correctness.fail.cpp Fri Oct 7 16:27:45 2016 @@ -28,11 +28,19 @@ int main() any a; - // expected-error@any:* 2 {{binding value of type '_Tp' (aka 'const TestType') to reference to type 'TestType' drops 'const' qualifier}} + // expected-error@any:* {{binding value of type 'const TestType' to reference to type 'TestType' drops 'const' qualifier}} + // expected-error@any:* {{static_assert failed "ValueType is required to be a reference or a CopyConstructible type"}} any_cast<TestType &>(static_cast<any const&>(a)); // expected-note {{requested here}} + + // expected-error@any:* {{cannot cast from lvalue of type 'const TestType' to rvalue reference type 'TestType &&'; types are not compatible}} + // expected-error@any:* {{static_assert failed "ValueType is required to be a reference or a CopyConstructible type"}} any_cast<TestType &&>(static_cast<any const&>(a)); // expected-note {{requested here}} - // expected-error@any:* 2 {{binding value of type '_Tp' (aka 'const TestType2') to reference to type 'TestType2' drops 'const' qualifier}} + // expected-error@any:* {{binding value of type 'const TestType2' to reference to type 'TestType2' drops 'const' qualifier}} + // expected-error@any:* {{static_assert failed "ValueType is required to be a reference or a CopyConstructible type"}} any_cast<TestType2 &>(static_cast<any const&&>(a)); // expected-note {{requested here}} + + // expected-error@any:* {{cannot cast from lvalue of type 'const TestType2' to rvalue reference type 'TestType2 &&'; types are not compatible}} + // expected-error@any:* {{static_assert failed "ValueType is required to be a reference or a CopyConstructible type"}} any_cast<TestType2 &&>(static_cast<any const&&>(a)); // expected-note {{requested here}} } Modified: libcxx/trunk/test/std/utilities/any/any.nonmembers/any.cast/not_copy_constructible.fail.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/any/any.nonmembers/any.cast/not_copy_constructible.fail.cpp?rev=283606&r1=283605&r2=283606&view=diff ============================================================================== --- libcxx/trunk/test/std/utilities/any/any.nonmembers/any.cast/not_copy_constructible.fail.cpp (original) +++ libcxx/trunk/test/std/utilities/any/any.nonmembers/any.cast/not_copy_constructible.fail.cpp Fri Oct 7 16:27:45 2016 @@ -31,15 +31,28 @@ struct no_copy { no_copy() {} no_copy(no_copy &&) {} -private: - no_copy(no_copy const &); + no_copy(no_copy const &) = delete; +}; + +struct no_move { + no_move() {} + no_move(no_move&&) = delete; + no_move(no_move const&) {} }; int main() { any a; + // expected-error@any:* {{static_assert failed "ValueType is required to be a reference or a CopyConstructible type"}} + // expected-error@any:* {{static_cast from 'no_copy' to 'no_copy' uses deleted function}} any_cast<no_copy>(static_cast<any&>(a)); // expected-note {{requested here}} + + // expected-error@any:* {{static_assert failed "ValueType is required to be a reference or a CopyConstructible type"}} + // expected-error@any:* {{static_cast from 'const no_copy' to 'no_copy' uses deleted function}} any_cast<no_copy>(static_cast<any const&>(a)); // expected-note {{requested here}} - any_cast<no_copy>(static_cast<any &&>(a)); // expected-note {{requested here}} - // expected-error@any:* 3 {{static_assert failed "_ValueType is required to be a reference or a CopyConstructible type."}} - // expected-error@any:* 2 {{calling a private constructor of class 'no_copy'}} -} \ No newline at end of file + + any_cast<no_copy>(static_cast<any &&>(a)); // OK + + // expected-error@any:* {{static_assert failed "ValueType is required to be an rvalue reference or a CopyConstructible type"}} + // expected-error@any:* {{static_cast from 'typename remove_reference<no_move &>::type' (aka 'no_move') to 'no_move' uses deleted function}} + any_cast<no_move>(static_cast<any &&>(a)); +} Added: libcxx/trunk/test/std/utilities/any/any.nonmembers/any.cast/rvalue_any_cast_request_lvalue.fail.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/any/any.nonmembers/any.cast/rvalue_any_cast_request_lvalue.fail.cpp?rev=283606&view=auto ============================================================================== --- libcxx/trunk/test/std/utilities/any/any.nonmembers/any.cast/rvalue_any_cast_request_lvalue.fail.cpp (added) +++ libcxx/trunk/test/std/utilities/any/any.nonmembers/any.cast/rvalue_any_cast_request_lvalue.fail.cpp Fri Oct 7 16:27:45 2016 @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <any> + +// template <class ValueType> +// ValueType any_cast(any &&); + +// Try and use the rvalue any_cast to cast to an lvalue reference + +#include <any> + +struct TestType {}; + +int main() +{ + using std::any; + using std::any_cast; + + any a; + // expected-error@any:* {{static_assert failed "ValueType is required to be an rvalue reference or a CopyConstructible type"}} + // expected-error@any:* {{non-const lvalue reference to type 'TestType' cannot bind to a temporary}} + any_cast<TestType &>(std::move(a)); // expected-note {{requested here}} + + // expected-error@any:* {{static_assert failed "ValueType is required to be an rvalue reference or a CopyConstructible type"}} + // expected-error@any:* {{non-const lvalue reference to type 'int' cannot bind to a temporary}} + any_cast<int&>(42); +} Modified: libcxx/trunk/test/std/utilities/any/any.nonmembers/make_any.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/any/any.nonmembers/make_any.pass.cpp?rev=283606&r1=283605&r2=283606&view=diff ============================================================================== --- libcxx/trunk/test/std/utilities/any/any.nonmembers/make_any.pass.cpp (original) +++ libcxx/trunk/test/std/utilities/any/any.nonmembers/make_any.pass.cpp Fri Oct 7 16:27:45 2016 @@ -99,7 +99,7 @@ static_assert(IsSmallObject<SmallThrows> struct LargeThrows { LargeThrows(int) { throw 42; } LargeThrows(std::initializer_list<int>, int) { throw 42; } - int data[10]; + int data[sizeof(std::any)]; }; static_assert(!IsSmallObject<LargeThrows>::value, ""); @@ -137,4 +137,4 @@ int main() { test_make_any_throws<LargeThrows>(); #endif -} \ No newline at end of file +} Modified: libcxx/trunk/test/support/any_helpers.h URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/support/any_helpers.h?rev=283606&r1=283605&r2=283606&view=diff ============================================================================== --- libcxx/trunk/test/support/any_helpers.h (original) +++ libcxx/trunk/test/support/any_helpers.h Fri Oct 7 16:27:45 2016 @@ -246,67 +246,6 @@ typedef large_type<> large; typedef large_type<1> large1; typedef large_type<2> large2; - -struct deleted_move -{ - static int count; - static int copied; - static int moved; - static int const_copied; - static int non_const_copied; - - static void reset() { - deleted_move::copied = 0; - deleted_move::moved = 0; - deleted_move::const_copied = 0; - deleted_move::non_const_copied = 0; - } - - int value; - - explicit deleted_move(int val = 0) : value(val) { - ++count; - } - explicit deleted_move(int, int val, int) : value(val) { - ++count; - } - deleted_move(std::initializer_list<int> il) : value(*il.begin()) { - ++count; - } - - deleted_move(deleted_move const & other) noexcept { - value = other.value; - ++count; - ++copied; - ++const_copied; - } - - deleted_move(deleted_move& other) noexcept { - value = other.value; - ++count; - ++copied; - ++non_const_copied; - } - - deleted_move(deleted_move && other) = delete; - - ~deleted_move() { - value = -1; - --count; - } - -private: - deleted_move& operator=(deleted_move const&) = delete; - deleted_move& operator=(deleted_move&&) = delete; -}; - -int deleted_move::count = 0; -int deleted_move::copied = 0; -int deleted_move::moved = 0; -int deleted_move::const_copied = 0; -int deleted_move::non_const_copied = 0; - - // The exception type thrown by 'small_throws_on_copy', 'large_throws_on_copy' // and 'throws_on_move'. struct my_any_exception {}; Modified: libcxx/trunk/test/support/test_macros.h URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/support/test_macros.h?rev=283606&r1=283605&r2=283606&view=diff ============================================================================== --- libcxx/trunk/test/support/test_macros.h (original) +++ libcxx/trunk/test/support/test_macros.h Fri Oct 7 16:27:45 2016 @@ -124,9 +124,11 @@ #if defined(_LIBCPP_VERSION) #define LIBCPP_ASSERT(...) assert(__VA_ARGS__) #define LIBCPP_STATIC_ASSERT(...) static_assert(__VA_ARGS__) +#define LIBCPP_ONLY(...) __VA_ARGS__ #else #define LIBCPP_ASSERT(...) ((void)0) #define LIBCPP_STATIC_ASSERT(...) ((void)0) +#define LIBCPP_ONLY(...) ((void)0) #endif #define ASSERT_NOEXCEPT(...) \ _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits