[libcxx] r283606 - Fix various issues in std::any and the related tests.

Eric Fiselier via cfe-commits cfe-commits at lists.llvm.org
Fri Oct 7 14:27:46 PDT 2016


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 at any:* 2 {{binding value of type '_Tp' (aka 'const TestType') to reference to type 'TestType' drops 'const' qualifier}}
+    // expected-error at any:* {{binding value of type 'const TestType' to reference to type 'TestType' drops 'const' qualifier}}
+    // expected-error at 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 at any:* {{cannot cast from lvalue of type 'const TestType' to rvalue reference type 'TestType &&'; types are not compatible}}
+    // expected-error at 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 at any:* 2 {{binding value of type '_Tp' (aka 'const TestType2') to reference to type 'TestType2' drops 'const' qualifier}}
+    // expected-error at any:* {{binding value of type 'const TestType2' to reference to type 'TestType2' drops 'const' qualifier}}
+    // expected-error at 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 at any:* {{cannot cast from lvalue of type 'const TestType2' to rvalue reference type 'TestType2 &&'; types are not compatible}}
+    // expected-error at 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 at any:* {{static_assert failed "ValueType is required to be a reference or a CopyConstructible type"}}
+    // expected-error at 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 at any:* {{static_assert failed "ValueType is required to be a reference or a CopyConstructible type"}}
+    // expected-error at 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 at any:* 3 {{static_assert failed "_ValueType is required to be a reference or a CopyConstructible type."}}
-    // expected-error at 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 at any:* {{static_assert failed "ValueType is required to be an rvalue reference or a CopyConstructible type"}}
+    // expected-error at 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 at any:* {{static_assert failed "ValueType is required to be an rvalue reference or a CopyConstructible type"}}
+    // expected-error at 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 at any:* {{static_assert failed "ValueType is required to be an rvalue reference or a CopyConstructible type"}}
+    // expected-error at 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(...) \




More information about the cfe-commits mailing list