PR69321 fix any_cast<T>(any*) for non-copyable T
authorJonathan Wakely <jwakely@redhat.com>
Fri, 20 Jan 2017 01:22:54 +0000 (01:22 +0000)
committerJonathan Wakely <redi@gcc.gnu.org>
Fri, 20 Jan 2017 01:22:54 +0000 (01:22 +0000)
PR libstdc++/69321
* include/experimental/any (__any_caster): Avoid instantiating
manager function for types that can't be stored in any.
* include/std/any (__any_caster): Likewise.
* testsuite/20_util/any/misc/any_cast.cc: Test non-copyable type.
* testsuite/experimental/any/misc/any_cast.cc: Likewise.

From-SVN: r244678

libstdc++-v3/ChangeLog
libstdc++-v3/include/experimental/any
libstdc++-v3/include/std/any
libstdc++-v3/testsuite/20_util/any/misc/any_cast.cc
libstdc++-v3/testsuite/experimental/any/misc/any_cast.cc

index 4cb727c8a44e9b31190f953858e3f8872869e047..b4be6e59890eac7d645c1497c686806625ef8b70 100644 (file)
@@ -1,5 +1,12 @@
 2017-01-20  Jonathan Wakely  <jwakely@redhat.com>
 
+       PR libstdc++/69321
+       * include/experimental/any (__any_caster): Avoid instantiating
+       manager function for types that can't be stored in any.
+       * include/std/any (__any_caster): Likewise.
+       * testsuite/20_util/any/misc/any_cast.cc: Test non-copyable type.
+       * testsuite/experimental/any/misc/any_cast.cc: Likewise.
+
        PR libstdc++/64903
        * include/bits/stl_algo.h (is_partitioned): Use increment instead of
        std::advance.
index d9f06cd025908dd2885d02784497f59e3c755f44..36c0680c25a6fb73eb8f823e17c5345c7b098df1 100644 (file)
@@ -415,7 +415,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp>
     void* __any_caster(const any* __any)
     {
-      if (__any->_M_manager != &any::_Manager<decay_t<_Tp>>::_S_manage)
+      struct _None { };
+      using _Up = decay_t<_Tp>;
+      using _Vp = conditional_t<is_copy_constructible<_Up>::value, _Up, _None>;
+      if (__any->_M_manager != &any::_Manager<_Vp>::_S_manage)
        return nullptr;
       any::_Arg __arg;
       __any->_M_manager(any::_Op_access, __any, &__arg);
index 8a6007564bed8b12956483fee81c02adde8b8303..e807617bdbb8bd590c424b245e687e21fc160ad1 100644 (file)
@@ -511,11 +511,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp>
     void* __any_caster(const any* __any)
     {
-      if (__any->_M_manager != &any::_Manager<decay_t<_Tp>>::_S_manage)
-       return nullptr;
-      any::_Arg __arg;
-      __any->_M_manager(any::_Op_access, __any, &__arg);
-      return __arg._M_obj;
+      if constexpr (is_copy_constructible_v<decay_t<_Tp>>)
+       {
+         if (__any->_M_manager == &any::_Manager<decay_t<_Tp>>::_S_manage)
+           {
+             any::_Arg __arg;
+             __any->_M_manager(any::_Op_access, __any, &__arg);
+             return __arg._M_obj;
+           }
+       }
+      return nullptr;
     }
 
   /**
index 559e4e9f9e17737bcbf784380c1ef05100c6ee82..72581e6b3650bb59a6dead751b6903b1592eed74 100644 (file)
@@ -118,10 +118,23 @@ void test04()
   ExplicitCopy ec2{any_cast<ExplicitCopy>(std::move(x))};
 }
 
+void test05()
+{
+  // PR libstdc++/69321
+  struct noncopyable {
+    noncopyable(noncopyable const&) = delete;
+  };
+
+  any a;
+  auto p = any_cast<noncopyable>(&a);
+  VERIFY( p == nullptr );
+}
+
 int main()
 {
   test01();
   test02();
   test03();
   test04();
+  test05();
 }
index b6cc114e9985821694ab97c34f97dab178f17e61..62ab1b38a33ab9286e341ada769891b53d4abe22 100644 (file)
@@ -105,9 +105,22 @@ void test03()
   MoveDeleted&& md3 = any_cast<MoveDeleted&&>(any(std::move(md)));
 }
 
+void test04()
+{
+  // PR libstdc++/69321
+  struct noncopyable {
+    noncopyable(noncopyable const&) = delete;
+  };
+
+  any a;
+  auto p = any_cast<noncopyable>(&a);
+  VERIFY( p == nullptr );
+}
+
 int main()
 {
   test01();
   test02();
   test03();
+  test04();
 }