From f9bfdfa2025512c8adb1e280e2df98e0512fbf30 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Wed, 24 Apr 2019 10:46:07 +0100 Subject: [PATCH] PR libstdc++/90220 Fix std::any_cast for function pointers PR libstdc++/90220 (partial) * include/std/any (any_cast(any*), any_cast(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. From-SVN: r270538 --- libstdc++-v3/ChangeLog | 6 ++++ libstdc++-v3/include/std/any | 10 +++--- .../testsuite/20_util/any/misc/any_cast.cc | 34 +++++++++++++++++++ 3 files changed, 46 insertions(+), 4 deletions(-) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 5b4d39cd5c8..8be3dcc860b 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,11 @@ 2019-04-24 Jonathan Wakely + PR libstdc++/90220 (partial) + * include/std/any (any_cast(any*), any_cast(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. + * testsuite/20_util/variant/run.cc: Catch exception by reference to prevent -Wcatch-value warning. 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 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 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 #include +#include #include #include @@ -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(&a); + VERIFY( p1 == nullptr ); + int (*p2)(int) = any_cast(&a); + VERIFY( p2 == nullptr ); + int (*p3)() = any_cast(&std::as_const(a)); + VERIFY( p3 == nullptr ); + + try { + any_cast(a); + VERIFY( false ); + } catch (const std::bad_any_cast&) { + } + + try { + any_cast(std::move(a)); + VERIFY( false ); + } catch (const std::bad_any_cast&) { + } + + try { + any_cast(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(); } -- 2.30.2