aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2019-04-24 10:46:07 +0100
committerJonathan Wakely <redi@gcc.gnu.org>2019-04-24 10:46:07 +0100
commitf9bfdfa2025512c8adb1e280e2df98e0512fbf30 (patch)
tree84039586f76d44d9032ec02651212a413295dc40
parentde6ae2ce078798024e647b8cc8afeca9d337817a (diff)
downloadgcc-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/ChangeLog6
-rw-r--r--libstdc++-v3/include/std/any10
-rw-r--r--libstdc++-v3/testsuite/20_util/any/misc/any_cast.cc34
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();
}