]> 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 15:09:02 +0000 (16:09 +0100)
committerJonathan Wakely <redi@gcc.gnu.org>
Thu, 23 May 2019 15:09:02 +0000 (16:09 +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: r271566

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

index 4f0466c3edfb43c6a6fb02bf3276e0a939e8c5b9..0dcf2f63b3540c8de3e2258ef267e0e593a8770e 100644 (file)
@@ -1,3 +1,14 @@
+2019-05-23  Jonathan Wakely  <jwakely@redhat.com>
+
+       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.
+
 2019-05-23  Jonathan Wakely  <jwakely@redhat.com>
 
        Backport from mainline
index 519e6536336cf2b16cbbae46b73d150f6d8f429e..41edfc359911bbd99547b76b2e8f326ce2e58773 100644 (file)
@@ -429,11 +429,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       // 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 b904cd6cdba1eb96716fb81f354ab57fd4cdf689..ecc062aba8a565196cc30ba39501c83fd782cd03 100644 (file)
@@ -513,6 +513,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     }
   // @}
 
+  /// @cond undocumented
   template<typename _Tp>
     void* __any_caster(const any* __any)
     {
@@ -526,8 +527,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);
@@ -535,6 +540,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        }
       return nullptr;
     }
+  /// @endcond
 
   /**
    * @brief Access the contained object.
index 81eda331fc875cbbb513ab1765705767b11b3905..84c0f50f265762618d70f10d7c541ad0fe493681 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 }
 }