aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2019-04-24 16:17:43 +0100
committerJonathan Wakely <redi@gcc.gnu.org>2019-04-24 16:17:43 +0100
commit92750002ef200965cb33aa5af68676b540564758 (patch)
treefa0e6eb0d5e98c5c22274cde7daca42c26449e3c
parent540bc8a8b1ff0aeb19ba6ac6304dd2e2075412c7 (diff)
downloadgcc-92750002ef200965cb33aa5af68676b540564758.zip
gcc-92750002ef200965cb33aa5af68676b540564758.tar.gz
gcc-92750002ef200965cb33aa5af68676b540564758.tar.bz2
PR libstdc++/90220 Fix std::any_cast for array types
Although the std::any constructors use decay_t to determine the type of the contained value, std::any_cast should use the un-decayed type (and so always fail for function and array types that decay to pointers). Using remove_cv_t is correct, because the condition for std::any_cast to return non-null is operand.type() == typeid(T) and typeid ignores top-level cv-qualifiers. PR libstdc++/90220 * include/std/any (__any_caster): Use remove_cv_t instead of decay_t. Avoid a runtime check for types that can never be stored in std::any. * testsuite/20_util/any/misc/any_cast.cc: Test std::any_cast with array types. From-SVN: r270547
-rw-r--r--libstdc++-v3/ChangeLog6
-rw-r--r--libstdc++-v3/include/std/any22
-rw-r--r--libstdc++-v3/testsuite/20_util/any/misc/any_cast.cc17
3 files changed, 38 insertions, 7 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 8be3dcc..2ab686b 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,5 +1,11 @@
2019-04-24 Jonathan Wakely <jwakely@redhat.com>
+ PR libstdc++/90220
+ * include/std/any (__any_caster): Use remove_cv_t instead of decay_t.
+ Avoid a runtime check for types that can never be stored in std::any.
+ * testsuite/20_util/any/misc/any_cast.cc: Test std::any_cast with
+ array types.
+
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.
diff --git a/libstdc++-v3/include/std/any b/libstdc++-v3/include/std/any
index 792db27..29fe03e 100644
--- a/libstdc++-v3/include/std/any
+++ b/libstdc++-v3/include/std/any
@@ -506,14 +506,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp>
void* __any_caster(const any* __any)
{
- if constexpr (is_copy_constructible_v<decay_t<_Tp>>)
+ // any_cast<T> returns non-null if __any->type() == typeid(T) and
+ // typeid(T) ignores cv-qualifiers so remove them:
+ using _Up = remove_cv_t<_Tp>;
+ // The contained value has a decayed type, so if decay_t<U> is not U,
+ // then it's not possible to have a contained value of type U:
+ if constexpr (!is_same_v<decay_t<_Up>, _Up>)
+ return nullptr;
+ // 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)
{
- if (__any->_M_manager == &any::_Manager<decay_t<_Tp>>::_S_manage)
- {
- any::_Arg __arg;
- __any->_M_manager(any::_Op_access, __any, &__arg);
- return __arg._M_obj;
- }
+ any::_Arg __arg;
+ __any->_M_manager(any::_Op_access, __any, &__arg);
+ return __arg._M_obj;
}
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 c9aeaae..b7fbbc5 100644
--- a/libstdc++-v3/testsuite/20_util/any/misc/any_cast.cc
+++ b/libstdc++-v3/testsuite/20_util/any/misc/any_cast.cc
@@ -154,6 +154,22 @@ void test06()
}
}
+void test07()
+{
+ int arr[3];
+ any a(arr);
+ VERIFY( a.type() == typeid(int*) ); // contained value is decayed
+
+ int (*p1)[3] = any_cast<int[3]>(&a);
+ VERIFY( a.type() != typeid(int[3]) ); // so any_cast should return nullptr
+ VERIFY( p1 == nullptr );
+ int (*p2)[] = any_cast<int[]>(&a);
+ VERIFY( a.type() != typeid(int[]) ); // so any_cast should return nullptr
+ VERIFY( p2 == nullptr );
+ const int (*p3)[] = any_cast<int[]>(&std::as_const(a));
+ VERIFY( p3 == nullptr );
+}
+
int main()
{
test01();
@@ -162,4 +178,5 @@ int main()
test04();
test05();
test06();
+ test07();
}