]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Make any_cast compare typeinfo as well as function pointers
authorJonathan Wakely <jwakely@redhat.com>
Thu, 23 May 2019 14:18:18 +0000 (15:18 +0100)
committerJonathan Wakely <redi@gcc.gnu.org>
Thu, 23 May 2019 14:18:18 +0000 (15:18 +0100)
It's possible for the function pointer comparison to fail even though
the type is correct, because the function could be defined multiple
times with different addresses when shared libraries are in use.

Retain the function pointer check for the common case where the check
succeeds, but compare typeinfo (if RTTI is enabled) if the first check
fails.

Backport from mainline
2019-05-23  Jonathan Wakely  <jwakely@redhat.com>

* include/experimental/any (__any_caster): Use RTTI if comparing
addresses fails, to support non-unique addresses in shared libraries.
* include/std/any (__any_caster): Likewise.
* testsuite/experimental/any/misc/any_cast_neg.cc: Use 0 for dg-error
line number.

From-SVN: r271559

libstdc++-v3/ChangeLog
libstdc++-v3/include/experimental/any
libstdc++-v3/include/std/any
libstdc++-v3/testsuite/experimental/any/misc/any_cast_neg.cc

index 494cf37da5f2161d83dfed8a7c4f9e58ae73615b..177491d68247149a8408feb32483e93dedce3bbb 100644 (file)
@@ -3,6 +3,15 @@
        Backport from mainline
        2019-05-23  Jonathan Wakely  <jwakely@redhat.com>
 
+       * include/experimental/any (__any_caster): Use RTTI if comparing
+       addresses fails, to support non-unique addresses in shared libraries.
+       * include/std/any (__any_caster): Likewise.
+       * testsuite/experimental/any/misc/any_cast_neg.cc: Use 0 for dg-error
+       line number.
+
+       Backport from mainline
+       2019-05-23  Jonathan Wakely  <jwakely@redhat.com>
+
        PR libstdc++/90220
        * include/experimental/any (__any_caster): Constrain to only be
        callable for object types. Use remove_cv_t instead of decay_t.
index 1ba29c7e0cf338b275aa31f67b7d3e964dd32950..33a2d514cf307685f2cacfbf47a07d86a5a8428f 100644 (file)
@@ -429,11 +429,18 @@ inline namespace fundamentals_v1
       // is explicitly specialized and has a no-op _S_manage function.
       using _Vp = conditional_t<__and_<__does_not_decay, __is_copyable>::value,
                                _Up, any::_Op>;
-      if (__any->_M_manager != &any::_Manager<_Vp>::_S_manage)
-       return nullptr;
-      any::_Arg __arg;
-      __any->_M_manager(any::_Op_access, __any, &__arg);
-      return __arg._M_obj;
+      // First try comparing function addresses, which works without RTTI
+      if (__any->_M_manager == &any::_Manager<_Vp>::_S_manage
+#if __cpp_rtti
+         || __any->type() == typeid(_Tp)
+#endif
+         )
+       {
+         any::_Arg __arg;
+         __any->_M_manager(any::_Op_access, __any, &__arg);
+         return __arg._M_obj;
+       }
+      return nullptr;
     }
 
   // This overload exists so that std::any_cast<void(*)()>(a) is well-formed.
index 8cbabdddd9b735479b65b7fac9516f915617ac2d..229c7c6b65ec5cbf38415da886bbb74e7f7c5c2c 100644 (file)
@@ -503,6 +503,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     }
   // @}
 
+  /// @cond undocumented
   template<typename _Tp>
     void* __any_caster(const any* __any)
     {
@@ -516,8 +517,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       // Only copy constructible types can be used for contained values:
       else if constexpr (!is_copy_constructible_v<_Up>)
        return nullptr;
-      // This check is equivalent to __any->type() == typeid(_Tp)
-      else if (__any->_M_manager == &any::_Manager<_Up>::_S_manage)
+      // First try comparing function addresses, which works without RTTI
+      else if (__any->_M_manager == &any::_Manager<_Up>::_S_manage
+#if __cpp_rtti
+         || __any->type() == typeid(_Tp)
+#endif
+         )
        {
          any::_Arg __arg;
          __any->_M_manager(any::_Op_access, __any, &__arg);
@@ -525,6 +530,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        }
       return nullptr;
     }
+  /// @endcond
 
   /**
    * @brief Access the contained object.
index 145e0be0ed40bc1383fcecafabda60ed4de8db4b..a197388565f17f10436e4617ba1463905158a463 100644 (file)
@@ -25,5 +25,5 @@ void test01()
   using std::experimental::any_cast;
 
   const any y(1);
-  any_cast<int&>(y); // { dg-error "qualifiers" "" { target { *-*-* } } 357 }
+  any_cast<int&>(y); // { dg-error "qualifiers" "" { target { *-*-* } } 0 }
 }