aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2017-01-20 01:22:54 +0000
committerJonathan Wakely <redi@gcc.gnu.org>2017-01-20 01:22:54 +0000
commit38a9e5a6c07d84274bc5d345b947d1c13351d590 (patch)
tree3d61b326d740e796dfbb370ca1db3de644acf9f2
parent01334be4a08330081eb74181faec5fbb4c30bcda (diff)
downloadgcc-38a9e5a6c07d84274bc5d345b947d1c13351d590.zip
gcc-38a9e5a6c07d84274bc5d345b947d1c13351d590.tar.gz
gcc-38a9e5a6c07d84274bc5d345b947d1c13351d590.tar.bz2
PR69321 fix any_cast<T>(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
-rw-r--r--libstdc++-v3/ChangeLog7
-rw-r--r--libstdc++-v3/include/experimental/any5
-rw-r--r--libstdc++-v3/include/std/any15
-rw-r--r--libstdc++-v3/testsuite/20_util/any/misc/any_cast.cc13
-rw-r--r--libstdc++-v3/testsuite/experimental/any/misc/any_cast.cc13
5 files changed, 47 insertions, 6 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 4cb727c..b4be6e5 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,5 +1,12 @@
2017-01-20 Jonathan Wakely <jwakely@redhat.com>
+ 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 d9f06cd..36c0680 100644
--- a/libstdc++-v3/include/experimental/any
+++ b/libstdc++-v3/include/experimental/any
@@ -415,7 +415,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp>
void* __any_caster(const any* __any)
{
- if (__any->_M_manager != &any::_Manager<decay_t<_Tp>>::_S_manage)
+ struct _None { };
+ using _Up = decay_t<_Tp>;
+ using _Vp = conditional_t<is_copy_constructible<_Up>::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 8a60075..e807617 100644
--- a/libstdc++-v3/include/std/any
+++ b/libstdc++-v3/include/std/any
@@ -511,11 +511,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp>
void* __any_caster(const any* __any)
{
- if (__any->_M_manager != &any::_Manager<decay_t<_Tp>>::_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<decay_t<_Tp>>)
+ {
+ 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;
+ }
+ }
+ 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 559e4e9..72581e6 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<ExplicitCopy>(std::move(x))};
}
+void test05()
+{
+ // PR libstdc++/69321
+ struct noncopyable {
+ noncopyable(noncopyable const&) = delete;
+ };
+
+ any a;
+ auto p = any_cast<noncopyable>(&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 b6cc114..62ab1b3 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<MoveDeleted&&>(any(std::move(md)));
}
+void test04()
+{
+ // PR libstdc++/69321
+ struct noncopyable {
+ noncopyable(noncopyable const&) = delete;
+ };
+
+ any a;
+ auto p = any_cast<noncopyable>(&a);
+ VERIFY( p == nullptr );
+}
+
int main()
{
test01();
test02();
test03();
+ test04();
}