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.
Tested powerpc64le-linux, committed to trunk. The PR describes two bugs in any_cast, but I might leave the fix for the other part until stage 1.
commit 1da13522c390bcb2bf70348656116a4d034aa9a6 Author: Jonathan Wakely <jwak...@redhat.com> Date: Wed Apr 24 10:05:30 2019 +0100 PR libstdc++/90220 Fix std::any_cast for function pointers 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. diff --git a/libstdc++-v3/include/std/any b/libstdc++-v3/include/std/any index b0553dccf22..792db27b061 100644 --- a/libstdc++-v3/include/std/any +++ b/libstdc++-v3/include/std/any @@ -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; } // @} diff --git a/libstdc++-v3/testsuite/20_util/any/misc/any_cast.cc b/libstdc++-v3/testsuite/20_util/any/misc/any_cast.cc index 8f19dc3ae0b..c9aeaae3366 100644 --- a/libstdc++-v3/testsuite/20_util/any/misc/any_cast.cc +++ b/libstdc++-v3/testsuite/20_util/any/misc/any_cast.cc @@ -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(); }