mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-11-27 13:54:19 +08:00
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
This commit is contained in:
parent
540bc8a8b1
commit
92750002ef
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user