diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2019-04-24 16:17:43 +0100 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2019-04-24 16:17:43 +0100 |
commit | 92750002ef200965cb33aa5af68676b540564758 (patch) | |
tree | fa0e6eb0d5e98c5c22274cde7daca42c26449e3c | |
parent | 540bc8a8b1ff0aeb19ba6ac6304dd2e2075412c7 (diff) | |
download | gcc-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/ChangeLog | 6 | ||||
-rw-r--r-- | libstdc++-v3/include/std/any | 22 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/20_util/any/misc/any_cast.cc | 17 |
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(); } |