diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2019-04-24 10:46:07 +0100 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2019-04-24 10:46:07 +0100 |
commit | f9bfdfa2025512c8adb1e280e2df98e0512fbf30 (patch) | |
tree | 84039586f76d44d9032ec02651212a413295dc40 | |
parent | de6ae2ce078798024e647b8cc8afeca9d337817a (diff) | |
download | gcc-f9bfdfa2025512c8adb1e280e2df98e0512fbf30.zip gcc-f9bfdfa2025512c8adb1e280e2df98e0512fbf30.tar.gz gcc-f9bfdfa2025512c8adb1e280e2df98e0512fbf30.tar.bz2 |
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.
From-SVN: r270538
-rw-r--r-- | libstdc++-v3/ChangeLog | 6 | ||||
-rw-r--r-- | libstdc++-v3/include/std/any | 10 | ||||
-rw-r--r-- | libstdc++-v3/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 5b4d39c..8be3dcc 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,11 @@ 2019-04-24 Jonathan Wakely <jwakely@redhat.com> + 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. + * 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 b0553dc..792db27 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 8f19dc3..c9aeaae 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(); } |