From 38a9e5a6c07d84274bc5d345b947d1c13351d590 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Fri, 20 Jan 2017 01:22:54 +0000 Subject: [PATCH] PR69321 fix any_cast(any*) for non-copyable T PR libstdc++/69321 * include/experimental/any (__any_caster): Avoid instantiating manager function for types that can't be stored in any. * include/std/any (__any_caster): Likewise. * testsuite/20_util/any/misc/any_cast.cc: Test non-copyable type. * testsuite/experimental/any/misc/any_cast.cc: Likewise. From-SVN: r244678 --- libstdc++-v3/ChangeLog | 7 +++++++ libstdc++-v3/include/experimental/any | 5 ++++- libstdc++-v3/include/std/any | 15 ++++++++++----- .../testsuite/20_util/any/misc/any_cast.cc | 13 +++++++++++++ .../testsuite/experimental/any/misc/any_cast.cc | 13 +++++++++++++ 5 files changed, 47 insertions(+), 6 deletions(-) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 4cb727c8a44..b4be6e59890 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,12 @@ 2017-01-20 Jonathan Wakely + PR libstdc++/69321 + * include/experimental/any (__any_caster): Avoid instantiating + manager function for types that can't be stored in any. + * include/std/any (__any_caster): Likewise. + * testsuite/20_util/any/misc/any_cast.cc: Test non-copyable type. + * testsuite/experimental/any/misc/any_cast.cc: Likewise. + PR libstdc++/64903 * include/bits/stl_algo.h (is_partitioned): Use increment instead of std::advance. diff --git a/libstdc++-v3/include/experimental/any b/libstdc++-v3/include/experimental/any index d9f06cd0259..36c0680c25a 100644 --- a/libstdc++-v3/include/experimental/any +++ b/libstdc++-v3/include/experimental/any @@ -415,7 +415,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template void* __any_caster(const any* __any) { - if (__any->_M_manager != &any::_Manager>::_S_manage) + struct _None { }; + using _Up = decay_t<_Tp>; + using _Vp = conditional_t::value, _Up, _None>; + if (__any->_M_manager != &any::_Manager<_Vp>::_S_manage) return nullptr; any::_Arg __arg; __any->_M_manager(any::_Op_access, __any, &__arg); diff --git a/libstdc++-v3/include/std/any b/libstdc++-v3/include/std/any index 8a6007564be..e807617bdbb 100644 --- a/libstdc++-v3/include/std/any +++ b/libstdc++-v3/include/std/any @@ -511,11 +511,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template void* __any_caster(const any* __any) { - if (__any->_M_manager != &any::_Manager>::_S_manage) - return nullptr; - any::_Arg __arg; - __any->_M_manager(any::_Op_access, __any, &__arg); - return __arg._M_obj; + if constexpr (is_copy_constructible_v>) + { + if (__any->_M_manager == &any::_Manager>::_S_manage) + { + 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 559e4e9f9e1..72581e6b365 100644 --- a/libstdc++-v3/testsuite/20_util/any/misc/any_cast.cc +++ b/libstdc++-v3/testsuite/20_util/any/misc/any_cast.cc @@ -118,10 +118,23 @@ void test04() ExplicitCopy ec2{any_cast(std::move(x))}; } +void test05() +{ + // PR libstdc++/69321 + struct noncopyable { + noncopyable(noncopyable const&) = delete; + }; + + any a; + auto p = any_cast(&a); + VERIFY( p == nullptr ); +} + int main() { test01(); test02(); test03(); test04(); + test05(); } diff --git a/libstdc++-v3/testsuite/experimental/any/misc/any_cast.cc b/libstdc++-v3/testsuite/experimental/any/misc/any_cast.cc index b6cc114e998..62ab1b38a33 100644 --- a/libstdc++-v3/testsuite/experimental/any/misc/any_cast.cc +++ b/libstdc++-v3/testsuite/experimental/any/misc/any_cast.cc @@ -105,9 +105,22 @@ void test03() MoveDeleted&& md3 = any_cast(any(std::move(md))); } +void test04() +{ + // PR libstdc++/69321 + struct noncopyable { + noncopyable(noncopyable const&) = delete; + }; + + any a; + auto p = any_cast(&a); + VERIFY( p == nullptr ); +} + int main() { test01(); test02(); test03(); + test04(); } -- 2.30.2