aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2019-05-23 15:13:18 +0100
committerJonathan Wakely <redi@gcc.gnu.org>2019-05-23 15:13:18 +0100
commitaa573a6a3e165632103f2f8defb9768106db6a61 (patch)
tree266886fa0da1ec2329d0dbbe73b11e45561df137
parent7dbab5dc84e3782fe6f366a985e507e2ea2726d2 (diff)
downloadgcc-aa573a6a3e165632103f2f8defb9768106db6a61.zip
gcc-aa573a6a3e165632103f2f8defb9768106db6a61.tar.gz
gcc-aa573a6a3e165632103f2f8defb9768106db6a61.tar.bz2
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. * 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. From-SVN: r271557
-rw-r--r--libstdc++-v3/ChangeLog4
-rw-r--r--libstdc++-v3/include/experimental/any17
-rw-r--r--libstdc++-v3/include/std/any10
3 files changed, 24 insertions, 7 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 460b734..2d557fc 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,5 +1,9 @@
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.
+
PR libstdc++/90220
* include/experimental/any (__any_caster): Constrain to only be
callable for object types. Use remove_cv_t instead of decay_t.
diff --git a/libstdc++-v3/include/experimental/any b/libstdc++-v3/include/experimental/any
index f1d4bbf..f7a4c8f 100644
--- a/libstdc++-v3/include/experimental/any
+++ b/libstdc++-v3/include/experimental/any
@@ -432,11 +432,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.
diff --git a/libstdc++-v3/include/std/any b/libstdc++-v3/include/std/any
index 8cbabdd..229c7c6 100644
--- a/libstdc++-v3/include/std/any
+++ b/libstdc++-v3/include/std/any
@@ -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.