public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] PR69321 fix any_cast<T>(any*) for non-copyable T
@ 2017-01-20  2:28 Jonathan Wakely
  0 siblings, 0 replies; only message in thread
From: Jonathan Wakely @ 2017-01-20  2:28 UTC (permalink / raw)
  To: libstdc++, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 507 bytes --]

any_cast must not trigger the instantiation of the manager function
for types which don't meet the requirements for being stored in an any
object.

	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.

Tested powerpc64le-linux, committed to trunk.


[-- Attachment #2: patch.txt --]
[-- Type: text/plain, Size: 3368 bytes --]

commit 55bf26e8ab076839ed9a45dbfe7ce20fd5290773
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Fri Jan 20 00:47:35 2017 +0000

    PR69321 fix any_cast<T>(any*) for non-copyable T
    
    	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.

diff --git a/libstdc++-v3/include/experimental/any b/libstdc++-v3/include/experimental/any
index d9f06cd..36c0680 100644
--- a/libstdc++-v3/include/experimental/any
+++ b/libstdc++-v3/include/experimental/any
@@ -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);
diff --git a/libstdc++-v3/include/std/any b/libstdc++-v3/include/std/any
index 8a60075..e807617 100644
--- a/libstdc++-v3/include/std/any
+++ b/libstdc++-v3/include/std/any
@@ -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;
     }
 
   /**
diff --git a/libstdc++-v3/testsuite/20_util/any/misc/any_cast.cc b/libstdc++-v3/testsuite/20_util/any/misc/any_cast.cc
index 559e4e9..72581e6 100644
--- a/libstdc++-v3/testsuite/20_util/any/misc/any_cast.cc
+++ b/libstdc++-v3/testsuite/20_util/any/misc/any_cast.cc
@@ -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();
 }
diff --git a/libstdc++-v3/testsuite/experimental/any/misc/any_cast.cc b/libstdc++-v3/testsuite/experimental/any/misc/any_cast.cc
index b6cc114..62ab1b3 100644
--- a/libstdc++-v3/testsuite/experimental/any/misc/any_cast.cc
+++ b/libstdc++-v3/testsuite/experimental/any/misc/any_cast.cc
@@ -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();
 }

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2017-01-20  1:25 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-01-20  2:28 [PATCH] PR69321 fix any_cast<T>(any*) for non-copyable T Jonathan Wakely

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).