PR libstdc++/90220 Fix std::any_cast for function pointers
authorJonathan Wakely <jwakely@redhat.com>
Wed, 24 Apr 2019 09:46:07 +0000 (10:46 +0100)
committerJonathan Wakely <redi@gcc.gnu.org>
Wed, 24 Apr 2019 09:46:07 +0000 (10:46 +0100)
PR libstdc++/90220 (partial)
* include/std/any (any_cast<T>(any*), any_cast<T>(const any*)): Do
not attempt ill-formed static_cast to pointers to non-object types.
* testsuite/20_util/any/misc/any_cast.cc: Test std::any_cast with
function types.

From-SVN: r270538

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

index 5b4d39cd5c8ed79c1e097429117837e6b678c6aa..8be3dcc860b9100a50c82f45e7ad8cdeb7bbf97e 100644 (file)
@@ -1,5 +1,11 @@
 2019-04-24  Jonathan Wakely  <jwakely@redhat.com>
 
+       PR libstdc++/90220 (partial)
+       * include/std/any (any_cast<T>(any*), any_cast<T>(const any*)): Do
+       not attempt ill-formed static_cast to pointers to non-object types.
+       * testsuite/20_util/any/misc/any_cast.cc: Test std::any_cast with
+       function types.
+
        * testsuite/20_util/variant/run.cc: Catch exception by reference to
        prevent -Wcatch-value warning.
 
index b0553dccf22448025603acabd7c34d5a113b4de5..792db27b061e7e3d9734b41d0cce7de48dc24f0d 100644 (file)
@@ -532,16 +532,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _ValueType>
     inline const _ValueType* any_cast(const any* __any) noexcept
     {
-      if (__any)
-       return static_cast<_ValueType*>(__any_caster<_ValueType>(__any));
+      if constexpr (is_object_v<_ValueType>)
+       if (__any)
+         return static_cast<_ValueType*>(__any_caster<_ValueType>(__any));
       return nullptr;
     }
 
   template<typename _ValueType>
     inline _ValueType* any_cast(any* __any) noexcept
     {
-      if (__any)
-       return static_cast<_ValueType*>(__any_caster<_ValueType>(__any));
+      if constexpr (is_object_v<_ValueType>)
+       if (__any)
+         return static_cast<_ValueType*>(__any_caster<_ValueType>(__any));
       return nullptr;
     }
   // @}
index 8f19dc3ae0b8e18bf78f92aab5a9a648bc832a7f..c9aeaae336684d3f46b1f3c71330016a57f743d8 100644 (file)
@@ -20,6 +20,7 @@
 
 #include <any>
 #include <string>
+#include <utility>
 #include <cstring>
 #include <testsuite_hooks.h>
 
@@ -121,6 +122,38 @@ void test05()
   VERIFY( p == nullptr );
 }
 
+void test06()
+{
+  // The contained value of a std::any is always an object type,
+  // but std::any_cast does not forbid checking for function types.
+
+  any a(1);
+  void (*p1)() = any_cast<void()>(&a);
+  VERIFY( p1 == nullptr );
+  int (*p2)(int) = any_cast<int(int)>(&a);
+  VERIFY( p2 == nullptr );
+  int (*p3)() = any_cast<int()>(&std::as_const(a));
+  VERIFY( p3 == nullptr );
+
+  try {
+    any_cast<int(&)()>(a);
+    VERIFY( false );
+  } catch (const std::bad_any_cast&) {
+  }
+
+  try {
+    any_cast<int(&)()>(std::move(a));
+    VERIFY( false );
+  } catch (const std::bad_any_cast&) {
+  }
+
+  try {
+    any_cast<int(&)()>(std::as_const(a));
+    VERIFY( false );
+  } catch (const std::bad_any_cast&) {
+  }
+}
+
 int main()
 {
   test01();
@@ -128,4 +161,5 @@ int main()
   test03();
   test04();
   test05();
+  test06();
 }