From: Jonathan Wakely Date: Thu, 23 May 2019 15:09:02 +0000 (+0100) Subject: Make any_cast compare typeinfo as well as function pointers X-Git-Tag: releases/gcc-7.5.0~426 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=610306767b5b0ffb21480a2ddb5cab0c3dd12a3e;p=thirdparty%2Fgcc.git Make any_cast compare typeinfo as well as function pointers 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 * 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 --- diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 4f0466c3edfb..0dcf2f63b354 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,14 @@ +2019-05-23 Jonathan Wakely + + Backport from mainline + 2019-05-23 Jonathan Wakely + + * 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 Backport from mainline diff --git a/libstdc++-v3/include/experimental/any b/libstdc++-v3/include/experimental/any index 519e6536336c..41edfc359911 100644 --- a/libstdc++-v3/include/experimental/any +++ b/libstdc++-v3/include/experimental/any @@ -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(a) is well-formed. diff --git a/libstdc++-v3/include/std/any b/libstdc++-v3/include/std/any index b904cd6cdba1..ecc062aba8a5 100644 --- a/libstdc++-v3/include/std/any +++ b/libstdc++-v3/include/std/any @@ -513,6 +513,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } // @} + /// @cond undocumented template 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. diff --git a/libstdc++-v3/testsuite/experimental/any/misc/any_cast_neg.cc b/libstdc++-v3/testsuite/experimental/any/misc/any_cast_neg.cc index 81eda331fc87..84c0f50f2657 100644 --- a/libstdc++-v3/testsuite/experimental/any/misc/any_cast_neg.cc +++ b/libstdc++-v3/testsuite/experimental/any/misc/any_cast_neg.cc @@ -25,5 +25,5 @@ void test01() using std::experimental::any_cast; const any y(1); - any_cast(y); // { dg-error "qualifiers" "" { target { *-*-* } } 357 } + any_cast(y); // { dg-error "qualifiers" "" { target { *-*-* } } 0 } }