From: Jonathan Wakely Date: Fri, 20 Jan 2017 01:22:54 +0000 (+0000) Subject: PR69321 fix any_cast(any*) for non-copyable T X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=38a9e5a6c07d84274bc5d345b947d1c13351d590;p=gcc.git 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 --- 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(); }