aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2015-08-14 12:51:18 +0100
committerJonathan Wakely <redi@gcc.gnu.org>2015-08-14 12:51:18 +0100
commit2548a4d6ba4d54393ae7947a7a8c9070d9c7e113 (patch)
tree632465c942818a2b37b76a4879f691df51e00467
parent357c9f7edc4154418f9862652b53fa8321e91d22 (diff)
downloadgcc-2548a4d6ba4d54393ae7947a7a8c9070d9c7e113.zip
gcc-2548a4d6ba4d54393ae7947a7a8c9070d9c7e113.tar.gz
gcc-2548a4d6ba4d54393ae7947a7a8c9070d9c7e113.tar.bz2
any (any::operator=(const any&)): Move check for self-assignment.
* include/experimental/any (any::operator=(const any&)): Move check for self-assignment. (any::operator=(any&&)): Add check for self-assignment. (any::operator=(_ValueType&&)): Constrain template argument. (any::swap(any&)): Add check for self-swap. * testsuite/experimental/any/assign/self.cc: Test move and swap. * testsuite/experimental/any/misc/any_cast_neg.cc: Update dg-error. From-SVN: r226894
-rw-r--r--libstdc++-v3/ChangeLog10
-rw-r--r--libstdc++-v3/include/experimental/any59
-rw-r--r--libstdc++-v3/testsuite/experimental/any/assign/self.cc54
-rw-r--r--libstdc++-v3/testsuite/experimental/any/misc/any_cast_neg.cc2
4 files changed, 94 insertions, 31 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 15fa9a2..0753951 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,5 +1,15 @@
2015-08-14 Jonathan Wakely <jwakely@redhat.com>
+ * include/experimental/any (any::operator=(const any&)): Move check
+ for self-assignment.
+ (any::operator=(any&&)): Add check for self-assignment.
+ (any::operator=(_ValueType&&)): Constrain template argument.
+ (any::swap(any&)): Add check for self-swap.
+ * testsuite/experimental/any/assign/self.cc: Test move and swap.
+ * testsuite/experimental/any/misc/any_cast_neg.cc: Update dg-error.
+
+2015-08-14 Jonathan Wakely <jwakely@redhat.com>
+
* include/experimental/array: Add feature-test macro.
* testsuite/experimental/array/neg.cc: Update dg-error.
diff --git a/libstdc++-v3/include/experimental/any b/libstdc++-v3/include/experimental/any
index fbb70a7..dae82b5 100644
--- a/libstdc++-v3/include/experimental/any
+++ b/libstdc++-v3/include/experimental/any
@@ -175,12 +175,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/// Copy the state of another object.
any& operator=(const any& __rhs)
{
- if (this == &__rhs)
- return *this;
-
if (__rhs.empty())
clear();
- else
+ else if (this != &__rhs)
{
if (!empty())
_M_manager(_Op_destroy, this, nullptr);
@@ -200,7 +197,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
if (__rhs.empty())
clear();
- else
+ else if (this != &__rhs)
{
if (!empty())
_M_manager(_Op_destroy, this, nullptr);
@@ -213,7 +210,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/// Store a copy of @p __rhs as the contained object.
template<typename _ValueType>
- any& operator=(_ValueType&& __rhs)
+ enable_if_t<!is_same<any, decay_t<_ValueType>>::value, any&>
+ operator=(_ValueType&& __rhs)
{
*this = any(std::forward<_ValueType>(__rhs));
return *this;
@@ -233,30 +231,33 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/// Exchange state with another object.
void swap(any& __rhs) noexcept
- {
- if (empty() && __rhs.empty())
- return;
+ {
+ if (empty() && __rhs.empty())
+ return;
- if (!empty() && !__rhs.empty())
- {
- any __tmp;
- _Arg __arg;
- __arg._M_any = &__tmp;
- __rhs._M_manager(_Op_xfer, &__rhs, &__arg);
- __arg._M_any = &__rhs;
- _M_manager(_Op_xfer, this, &__arg);
- __arg._M_any = this;
- __tmp._M_manager(_Op_xfer, &__tmp, &__arg);
- }
- else
- {
- any* __empty = empty() ? this : &__rhs;
- any* __full = empty() ? &__rhs : this;
- _Arg __arg;
- __arg._M_any = __empty;
- __full->_M_manager(_Op_xfer, __full, &__arg);
- }
- }
+ if (!empty() && !__rhs.empty())
+ {
+ if (this == &__rhs)
+ return;
+
+ any __tmp;
+ _Arg __arg;
+ __arg._M_any = &__tmp;
+ __rhs._M_manager(_Op_xfer, &__rhs, &__arg);
+ __arg._M_any = &__rhs;
+ _M_manager(_Op_xfer, this, &__arg);
+ __arg._M_any = this;
+ __tmp._M_manager(_Op_xfer, &__tmp, &__arg);
+ }
+ else
+ {
+ any* __empty = empty() ? this : &__rhs;
+ any* __full = empty() ? &__rhs : this;
+ _Arg __arg;
+ __arg._M_any = __empty;
+ __full->_M_manager(_Op_xfer, __full, &__arg);
+ }
+ }
// observers
diff --git a/libstdc++-v3/testsuite/experimental/any/assign/self.cc b/libstdc++-v3/testsuite/experimental/any/assign/self.cc
index 0fb9566..79c6f0f 100644
--- a/libstdc++-v3/testsuite/experimental/any/assign/self.cc
+++ b/libstdc++-v3/testsuite/experimental/any/assign/self.cc
@@ -18,8 +18,17 @@
// { dg-options "-std=gnu++14" }
#include <experimental/any>
+#include <set>
#include <testsuite_hooks.h>
+std::set<const void*> live_objects;
+
+struct A {
+ A() { live_objects.insert(this); }
+ ~A() { live_objects.erase(this); }
+ A(const A& a) { VERIFY(live_objects.count(&a)); live_objects.insert(this); }
+};
+
void
test01()
{
@@ -29,13 +38,56 @@ test01()
a = a;
VERIFY( a.empty() );
- a = 1;
+ a = A{};
a = a;
VERIFY( !a.empty() );
+
+ a.clear();
+ VERIFY( live_objects.empty() );
+}
+
+void
+test02()
+{
+ using std::experimental::any;
+
+ struct X {
+ any a;
+ };
+
+ X x;
+ std::swap(x, x); // results in "self-move-assignment" of X::a
+ VERIFY( x.a.empty() );
+
+ x.a = A{};
+ std::swap(x, x); // results in "self-move-assignment" of X::a
+ VERIFY( !x.a.empty() );
+
+ x.a.clear();
+ VERIFY( live_objects.empty() );
+}
+
+void
+test03()
+{
+ using std::experimental::any;
+
+ any a;
+ a.swap(a);
+ VERIFY( a.empty() );
+
+ a = A{};
+ a.swap(a);
+ VERIFY( !a.empty() );
+
+ a.clear();
+ VERIFY( live_objects.empty() );
}
int
main()
{
test01();
+ test02();
+ test03();
}
diff --git a/libstdc++-v3/testsuite/experimental/any/misc/any_cast_neg.cc b/libstdc++-v3/testsuite/experimental/any/misc/any_cast_neg.cc
index b88592a..1d1180c 100644
--- a/libstdc++-v3/testsuite/experimental/any/misc/any_cast_neg.cc
+++ b/libstdc++-v3/testsuite/experimental/any/misc/any_cast_neg.cc
@@ -26,5 +26,5 @@ void test01()
using std::experimental::any_cast;
const any y(1);
- any_cast<int&>(y); // { dg-error "qualifiers" "" { target { *-*-* } } 359 }
+ any_cast<int&>(y); // { dg-error "qualifiers" "" { target { *-*-* } } 360 }
}