Fix for PR18735 - self-assignment for map/multimap gives incorrect results in C++03
git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@201021 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/map b/include/map
index 009e8e2..9779b70 100644
--- a/include/map
+++ b/include/map
@@ -884,10 +884,12 @@
#if __cplusplus >= 201103L
__tree_ = __m.__tree_;
#else
- __tree_.clear();
- __tree_.value_comp() = __m.__tree_.value_comp();
- __tree_.__copy_assign_alloc(__m.__tree_);
- insert(__m.begin(), __m.end());
+ if (this != &__m) {
+ __tree_.clear();
+ __tree_.value_comp() = __m.__tree_.value_comp();
+ __tree_.__copy_assign_alloc(__m.__tree_);
+ insert(__m.begin(), __m.end());
+ }
#endif
return *this;
}
@@ -1616,10 +1618,12 @@
#if __cplusplus >= 201103L
__tree_ = __m.__tree_;
#else
- __tree_.clear();
- __tree_.value_comp() = __m.__tree_.value_comp();
- __tree_.__copy_assign_alloc(__m.__tree_);
- insert(__m.begin(), __m.end());
+ if (this != &__m) {
+ __tree_.clear();
+ __tree_.value_comp() = __m.__tree_.value_comp();
+ __tree_.__copy_assign_alloc(__m.__tree_);
+ insert(__m.begin(), __m.end());
+ }
#endif
return *this;
}
diff --git a/include/unordered_map b/include/unordered_map
index 78fee48..4e2298b 100644
--- a/include/unordered_map
+++ b/include/unordered_map
@@ -831,12 +831,14 @@
#if __cplusplus >= 201103L
__table_ = __u.__table_;
#else
- __table_.clear();
- __table_.hash_function() = __u.__table_.hash_function();
- __table_.key_eq() = __u.__table_.key_eq();
- __table_.max_load_factor() = __u.__table_.max_load_factor();
- __table_.__copy_assign_alloc(__u.__table_);
- insert(__u.begin(), __u.end());
+ if (this != &__u) {
+ __table_.clear();
+ __table_.hash_function() = __u.__table_.hash_function();
+ __table_.key_eq() = __u.__table_.key_eq();
+ __table_.max_load_factor() = __u.__table_.max_load_factor();
+ __table_.__copy_assign_alloc(__u.__table_);
+ insert(__u.begin(), __u.end());
+ }
#endif
return *this;
}
@@ -1567,12 +1569,14 @@
#if __cplusplus >= 201103L
__table_ = __u.__table_;
#else
- __table_.clear();
- __table_.hash_function() = __u.__table_.hash_function();
- __table_.key_eq() = __u.__table_.key_eq();
- __table_.max_load_factor() = __u.__table_.max_load_factor();
- __table_.__copy_assign_alloc(__u.__table_);
- insert(__u.begin(), __u.end());
+ if (this != &__u) {
+ __table_.clear();
+ __table_.hash_function() = __u.__table_.hash_function();
+ __table_.key_eq() = __u.__table_.key_eq();
+ __table_.max_load_factor() = __u.__table_.max_load_factor();
+ __table_.__copy_assign_alloc(__u.__table_);
+ insert(__u.begin(), __u.end());
+ }
#endif
return *this;
}
diff --git a/test/containers/associative/map/map.cons/copy_assign.pass.cpp b/test/containers/associative/map/map.cons/copy_assign.pass.cpp
index ac05e29..a1bcb30 100644
--- a/test/containers/associative/map/map.cons/copy_assign.pass.cpp
+++ b/test/containers/associative/map/map.cons/copy_assign.pass.cpp
@@ -59,6 +59,21 @@
}
{
typedef std::pair<const int, double> V;
+ const V ar[] =
+ {
+ V(1, 1),
+ V(2, 1),
+ V(3, 1),
+ };
+ std::map<int, double> m(ar, ar+sizeof(ar)/sizeof(ar[0]));
+ std::map<int, double> *p = &m;
+ m = *p;
+
+ assert(m.size() == 3);
+ assert(std::equal(m.begin(), m.end(), ar));
+ }
+ {
+ typedef std::pair<const int, double> V;
V ar[] =
{
V(1, 1),
diff --git a/test/containers/associative/multimap/multimap.cons/copy_assign.pass.cpp b/test/containers/associative/multimap/multimap.cons/copy_assign.pass.cpp
index f00f0fe..2bdc4d6 100644
--- a/test/containers/associative/multimap/multimap.cons/copy_assign.pass.cpp
+++ b/test/containers/associative/multimap/multimap.cons/copy_assign.pass.cpp
@@ -50,6 +50,26 @@
}
{
typedef std::pair<const int, double> V;
+ const V ar[] =
+ {
+ V(1, 1),
+ V(1, 1.5),
+ V(1, 2),
+ V(2, 1),
+ V(2, 1.5),
+ V(2, 2),
+ V(3, 1),
+ V(3, 1.5),
+ V(3, 2),
+ };
+ std::multimap<int, double> m(ar, ar+sizeof(ar)/sizeof(ar[0]));
+ std::multimap<int, double> *p = &m;
+ m = *p;
+ assert(m.size() == sizeof(ar)/sizeof(ar[0]));
+ assert(std::equal(m.begin(), m.end(), ar));
+ }
+ {
+ typedef std::pair<const int, double> V;
V ar[] =
{
V(1, 1),
diff --git a/test/containers/associative/multiset/multiset.cons/copy_assign.pass.cpp b/test/containers/associative/multiset/multiset.cons/copy_assign.pass.cpp
index 19bdd71..cca6363 100644
--- a/test/containers/associative/multiset/multiset.cons/copy_assign.pass.cpp
+++ b/test/containers/associative/multiset/multiset.cons/copy_assign.pass.cpp
@@ -70,6 +70,26 @@
}
{
typedef int V;
+ const V ar[] =
+ {
+ 1,
+ 1,
+ 1,
+ 2,
+ 2,
+ 2,
+ 3,
+ 3,
+ 3
+ };
+ std::multiset<int> m(ar, ar+sizeof(ar)/sizeof(ar[0]));
+ std::multiset<int> *p = &m;
+ m = *p;
+ assert(m.size() == 9);
+ assert(std::equal(m.begin(), m.end(), ar));
+ }
+ {
+ typedef int V;
V ar[] =
{
1,
diff --git a/test/containers/associative/set/set.cons/copy_assign.pass.cpp b/test/containers/associative/set/set.cons/copy_assign.pass.cpp
index ae83eb3..7f0f044 100644
--- a/test/containers/associative/set/set.cons/copy_assign.pass.cpp
+++ b/test/containers/associative/set/set.cons/copy_assign.pass.cpp
@@ -58,6 +58,21 @@
}
{
typedef int V;
+ const V ar[] =
+ {
+ 1,
+ 2,
+ 3
+ };
+ std::set<int> m(ar, ar+sizeof(ar)/sizeof(ar[0]));
+ std::set<int> *p = &m;
+ m = *p;
+
+ assert(m.size() == 3);
+ assert(std::equal(m.begin(), m.end(), ar));
+ }
+ {
+ typedef int V;
V ar[] =
{
1,
diff --git a/test/containers/unord/unord.map/unord.map.cnstr/assign_copy.pass.cpp b/test/containers/unord/unord.map/unord.map.cnstr/assign_copy.pass.cpp
index 928377b..622ce50 100644
--- a/test/containers/unord/unord.map/unord.map.cnstr/assign_copy.pass.cpp
+++ b/test/containers/unord/unord.map/unord.map.cnstr/assign_copy.pass.cpp
@@ -73,6 +73,24 @@
assert(c.max_load_factor() == 1);
}
{
+ typedef std::unordered_map<int, std::string> C;
+ typedef std::pair<const int, std::string> P;
+ const P a[] =
+ {
+ P(1, "one"),
+ P(2, "two"),
+ P(3, "three"),
+ P(4, "four"),
+ P(1, "four"),
+ P(2, "four"),
+ };
+ C c(a, a + sizeof(a)/sizeof(a[0]));
+ C *p = &c;
+ c = *p;
+ assert(c.size() == 4);
+ assert(std::is_permutation(c.begin(), c.end(), a));
+ }
+ {
typedef other_allocator<std::pair<const int, std::string> > A;
typedef std::unordered_map<int, std::string,
test_hash<std::hash<int> >,
diff --git a/test/containers/unord/unord.multimap/unord.multimap.cnstr/assign_copy.pass.cpp b/test/containers/unord/unord.multimap/unord.multimap.cnstr/assign_copy.pass.cpp
index 4f47c78..df566b3 100644
--- a/test/containers/unord/unord.multimap/unord.multimap.cnstr/assign_copy.pass.cpp
+++ b/test/containers/unord/unord.multimap/unord.multimap.cnstr/assign_copy.pass.cpp
@@ -87,6 +87,24 @@
assert(c.max_load_factor() == 1);
}
{
+ typedef std::unordered_multimap<int, std::string> C;
+ typedef std::pair<const int, std::string> P;
+ const P a[] =
+ {
+ P(1, "one"),
+ P(2, "two"),
+ P(3, "three"),
+ P(4, "four"),
+ P(1, "four"),
+ P(2, "four"),
+ };
+ C c(a, a+sizeof(a)/sizeof(a[0]));
+ C *p = &c;
+ c = *p;
+ assert(c.size() == 6);
+ assert(std::is_permutation(c.begin(), c.end(), a));
+ }
+ {
typedef other_allocator<std::pair<const int, std::string> > A;
typedef std::unordered_multimap<int, std::string,
test_hash<std::hash<int> >,
diff --git a/test/containers/unord/unord.multiset/unord.multiset.cnstr/assign_copy.pass.cpp b/test/containers/unord/unord.multiset/unord.multiset.cnstr/assign_copy.pass.cpp
index f634994..2042f69 100644
--- a/test/containers/unord/unord.multiset/unord.multiset.cnstr/assign_copy.pass.cpp
+++ b/test/containers/unord/unord.multiset/unord.multiset.cnstr/assign_copy.pass.cpp
@@ -80,6 +80,25 @@
assert(c.max_load_factor() == 1);
}
{
+ typedef std::unordered_multiset<int> C;
+ typedef int P;
+ P a[] =
+ {
+ P(1),
+ P(2),
+ P(3),
+ P(4),
+ P(1),
+ P(2)
+ };
+ C c(a, a + sizeof(a)/sizeof(a[0]));
+ C *p = &c;
+ c = *p;
+
+ assert(c.size() == 6);
+ assert(std::is_permutation(c.begin(), c.end(), a));
+ }
+ {
typedef other_allocator<int> A;
typedef std::unordered_multiset<int,
test_hash<std::hash<int> >,
diff --git a/test/containers/unord/unord.set/unord.set.cnstr/assign_copy.pass.cpp b/test/containers/unord/unord.set/unord.set.cnstr/assign_copy.pass.cpp
index a1f8c48..6925e30 100644
--- a/test/containers/unord/unord.set/unord.set.cnstr/assign_copy.pass.cpp
+++ b/test/containers/unord/unord.set/unord.set.cnstr/assign_copy.pass.cpp
@@ -72,6 +72,24 @@
assert(c.max_load_factor() == 1);
}
{
+ typedef std::unordered_set<int> C;
+ typedef int P;
+ P a[] =
+ {
+ P(1),
+ P(2),
+ P(3),
+ P(4),
+ P(1),
+ P(2)
+ };
+ C c(a, a + sizeof(a)/sizeof(a[0]));
+ C *p = &c;
+ c = *p;
+ assert(c.size() == 4);
+ assert(std::is_permutation(c.begin(), c.end(), a));
+ }
+ {
typedef other_allocator<int> A;
typedef std::unordered_set<int,
test_hash<std::hash<int> >,