[libcxx-commits] [libcxx] b8608b8 - [libc++] Use addressof in assignment operator.

Mark de Wever via libcxx-commits libcxx-commits at lists.llvm.org
Thu Oct 7 09:10:52 PDT 2021


Author: Mark de Wever
Date: 2021-10-07T18:10:47+02:00
New Revision: b8608b87239ca7817d1536376a8ce4b5265747ee

URL: https://github.com/llvm/llvm-project/commit/b8608b87239ca7817d1536376a8ce4b5265747ee
DIFF: https://github.com/llvm/llvm-project/commit/b8608b87239ca7817d1536376a8ce4b5265747ee.diff

LOG: [libc++] Use addressof in assignment operator.

Replace `&__rhs` with `_VSTD::addressof(__rhs)` to guard against ADL hijacking
of `operator&` in `operator=`. Thanks to @CaseyCarter for bringing it to our
attention.

Similar issues with hijacking `operator&` still exist, they will be
addressed separately.

Reviewed By: #libc, Quuxplusone, ldionne

Differential Revision: https://reviews.llvm.org/D110852

Added: 
    libcxx/test/std/containers/associative/map/map.cons/copy_assign.addressof.compile.pass.cpp
    libcxx/test/std/containers/associative/multimap/multimap.cons/copy_assign.addressof.compile.pass.cpp
    libcxx/test/std/containers/associative/multiset/multiset.cons/copy_assign.addressof.compile.pass.cpp
    libcxx/test/std/containers/associative/set/set.cons/copy_assign.addressof.compile.pass.cpp
    libcxx/test/std/containers/container.adaptors/priority.queue/priqueue.cons/assign_copy.addressof.compile.pass.cpp
    libcxx/test/std/containers/container.adaptors/queue/queue.defn/assign_copy.addressof.compile.pass.cpp
    libcxx/test/std/containers/sequences/array/array.cons/implicit_copy.addressof.compile.pass.cpp
    libcxx/test/std/containers/sequences/deque/deque.cons/move_assign.addressof.compile.pass.cpp
    libcxx/test/std/containers/sequences/forwardlist/forwardlist.cons/assign_copy.addressof.compile.pass.cpp
    libcxx/test/std/containers/sequences/list/list.cons/assign_copy.addressof.compile.pass.cpp
    libcxx/test/std/containers/sequences/vector/vector.cons/assign_copy.addressof.compile.pass.cpp
    libcxx/test/std/containers/unord/unord.map/unord.map.cnstr/assign_copy.addressof.compile.pass.cpp
    libcxx/test/std/containers/unord/unord.multimap/unord.multimap.cnstr/assign_copy.addressof.compile.pass.cpp
    libcxx/test/std/containers/unord/unord.multiset/unord.multiset.cnstr/assign_copy.addressof.compile.pass.cpp
    libcxx/test/std/containers/unord/unord.set/unord.set.cnstr/assign_copy.addressof.compile.pass.cpp
    libcxx/test/std/numerics/numarray/template.valarray/valarray.assign/value_assign.addressof.compile.pass.cpp
    libcxx/test/support/operator_hijacker.h

Modified: 
    libcxx/include/__hash_table
    libcxx/include/__tree
    libcxx/include/deque
    libcxx/include/forward_list
    libcxx/include/list
    libcxx/include/map
    libcxx/include/unordered_map
    libcxx/include/valarray
    libcxx/include/vector

Removed: 
    


################################################################################
diff  --git a/libcxx/include/__hash_table b/libcxx/include/__hash_table
index eb99e60c5e0d..b7bd17436fb3 100644
--- a/libcxx/include/__hash_table
+++ b/libcxx/include/__hash_table
@@ -1541,7 +1541,7 @@ template <class _Tp, class _Hash, class _Equal, class _Alloc>
 __hash_table<_Tp, _Hash, _Equal, _Alloc>&
 __hash_table<_Tp, _Hash, _Equal, _Alloc>::operator=(const __hash_table& __u)
 {
-    if (this != &__u)
+    if (this != _VSTD::addressof(__u))
     {
         __copy_assign_alloc(__u);
         hash_function() = __u.hash_function();

diff  --git a/libcxx/include/__tree b/libcxx/include/__tree
index 57ac275b0d8a..f3f2e8d15f5d 100644
--- a/libcxx/include/__tree
+++ b/libcxx/include/__tree
@@ -1612,7 +1612,7 @@ template <class _Tp, class _Compare, class _Allocator>
 __tree<_Tp, _Compare, _Allocator>&
 __tree<_Tp, _Compare, _Allocator>::operator=(const __tree& __t)
 {
-    if (this != &__t)
+    if (this != _VSTD::addressof(__t))
     {
         value_comp() = __t.value_comp();
         __copy_assign_alloc(__t);

diff  --git a/libcxx/include/deque b/libcxx/include/deque
index 3b1291139feb..12e0399eaa01 100644
--- a/libcxx/include/deque
+++ b/libcxx/include/deque
@@ -1649,7 +1649,7 @@ template <class _Tp, class _Allocator>
 deque<_Tp, _Allocator>&
 deque<_Tp, _Allocator>::operator=(const deque& __c)
 {
-    if (this != &__c)
+    if (this != _VSTD::addressof(__c))
     {
         __copy_assign_alloc(__c);
         assign(__c.begin(), __c.end());

diff  --git a/libcxx/include/forward_list b/libcxx/include/forward_list
index 30b28d5571af..3454a784a1ca 100644
--- a/libcxx/include/forward_list
+++ b/libcxx/include/forward_list
@@ -990,7 +990,7 @@ template <class _Tp, class _Alloc>
 forward_list<_Tp, _Alloc>&
 forward_list<_Tp, _Alloc>::operator=(const forward_list& __x)
 {
-    if (this != &__x)
+    if (this != _VSTD::addressof(__x))
     {
         base::__copy_assign_alloc(__x);
         assign(__x.begin(), __x.end());

diff  --git a/libcxx/include/list b/libcxx/include/list
index 6030055c0753..b5b98af0654a 100644
--- a/libcxx/include/list
+++ b/libcxx/include/list
@@ -1392,7 +1392,7 @@ inline
 list<_Tp, _Alloc>&
 list<_Tp, _Alloc>::operator=(const list& __c)
 {
-    if (this != &__c)
+    if (this != _VSTD::addressof(__c))
     {
         base::__copy_assign_alloc(__c);
         assign(__c.begin(), __c.end());

diff  --git a/libcxx/include/map b/libcxx/include/map
index 25b75af377b0..667dc0e3f883 100644
--- a/libcxx/include/map
+++ b/libcxx/include/map
@@ -1036,7 +1036,7 @@ public:
 #ifndef _LIBCPP_CXX03_LANG
             __tree_ = __m.__tree_;
 #else
-            if (this != &__m) {
+            if (this != _VSTD::addressof(__m)) {
                 __tree_.clear();
                 __tree_.value_comp() = __m.__tree_.value_comp();
                 __tree_.__copy_assign_alloc(__m.__tree_);
@@ -1820,7 +1820,7 @@ public:
 #ifndef _LIBCPP_CXX03_LANG
             __tree_ = __m.__tree_;
 #else
-            if (this != &__m) {
+            if (this != _VSTD::addressof(__m)) {
                 __tree_.clear();
                 __tree_.value_comp() = __m.__tree_.value_comp();
                 __tree_.__copy_assign_alloc(__m.__tree_);

diff  --git a/libcxx/include/unordered_map b/libcxx/include/unordered_map
index a420c53f65fe..c6cd5e1c52a5 100644
--- a/libcxx/include/unordered_map
+++ b/libcxx/include/unordered_map
@@ -1056,7 +1056,7 @@ public:
 #ifndef _LIBCPP_CXX03_LANG
         __table_ = __u.__table_;
 #else
-        if (this != &__u) {
+        if (this != _VSTD::addressof(__u)) {
             __table_.clear();
             __table_.hash_function() = __u.__table_.hash_function();
             __table_.key_eq() = __u.__table_.key_eq();
@@ -1988,7 +1988,7 @@ public:
 #ifndef _LIBCPP_CXX03_LANG
         __table_ = __u.__table_;
 #else
-        if (this != &__u) {
+        if (this != _VSTD::addressof(__u)) {
             __table_.clear();
             __table_.hash_function() = __u.__table_.hash_function();
             __table_.key_eq() = __u.__table_.key_eq();

diff  --git a/libcxx/include/valarray b/libcxx/include/valarray
index 6e25514a6a3a..9a64839bd6da 100644
--- a/libcxx/include/valarray
+++ b/libcxx/include/valarray
@@ -3048,7 +3048,7 @@ template <class _Tp>
 valarray<_Tp>&
 valarray<_Tp>::operator=(const valarray& __v)
 {
-    if (this != &__v)
+    if (this != _VSTD::addressof(__v))
         return __assign_range(__v.__begin_, __v.__end_);
     return *this;
 }

diff  --git a/libcxx/include/vector b/libcxx/include/vector
index 626c917f3a6d..beec1b735185 100644
--- a/libcxx/include/vector
+++ b/libcxx/include/vector
@@ -1406,7 +1406,7 @@ inline _LIBCPP_INLINE_VISIBILITY
 vector<_Tp, _Allocator>&
 vector<_Tp, _Allocator>::operator=(const vector& __x)
 {
-    if (this != &__x)
+    if (this != _VSTD::addressof(__x))
     {
         __base::__copy_assign_alloc(__x);
         assign(__x.__begin_, __x.__end_);
@@ -2859,7 +2859,7 @@ template <class _Allocator>
 vector<bool, _Allocator>&
 vector<bool, _Allocator>::operator=(const vector& __v)
 {
-    if (this != &__v)
+    if (this != _VSTD::addressof(__v))
     {
         __copy_assign_alloc(__v);
         if (__v.__size_)

diff  --git a/libcxx/test/std/containers/associative/map/map.cons/copy_assign.addressof.compile.pass.cpp b/libcxx/test/std/containers/associative/map/map.cons/copy_assign.addressof.compile.pass.cpp
new file mode 100644
index 000000000000..9909ef841b87
--- /dev/null
+++ b/libcxx/test/std/containers/associative/map/map.cons/copy_assign.addressof.compile.pass.cpp
@@ -0,0 +1,33 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <map>
+
+// class map
+
+// map& operator=(const map& m);
+
+// Validate whether the container can be copy-assigned with an ADL-hijacking operator&
+
+#include <map>
+
+#include "test_macros.h"
+#include "operator_hijacker.h"
+
+void test() {
+  {
+    std::map<int, operator_hijacker> mo;
+    std::map<int, operator_hijacker> m;
+    m = mo;
+  }
+  {
+    std::map<operator_hijacker, int> mo;
+    std::map<operator_hijacker, int> m;
+    m = mo;
+  }
+}

diff  --git a/libcxx/test/std/containers/associative/multimap/multimap.cons/copy_assign.addressof.compile.pass.cpp b/libcxx/test/std/containers/associative/multimap/multimap.cons/copy_assign.addressof.compile.pass.cpp
new file mode 100644
index 000000000000..86288390af0e
--- /dev/null
+++ b/libcxx/test/std/containers/associative/multimap/multimap.cons/copy_assign.addressof.compile.pass.cpp
@@ -0,0 +1,33 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <map>
+
+// class multimap
+
+// multimap& operator=(const multimap& m);
+
+// Validate whether the container can be copy-assigned with an ADL-hijacking operator&
+
+#include <map>
+
+#include "test_macros.h"
+#include "operator_hijacker.h"
+
+void test() {
+  {
+    std::multimap<int, operator_hijacker> mo;
+    std::multimap<int, operator_hijacker> m;
+    m = mo;
+  }
+  {
+    std::multimap<operator_hijacker, int> mo;
+    std::multimap<operator_hijacker, int> m;
+    m = mo;
+  }
+}

diff  --git a/libcxx/test/std/containers/associative/multiset/multiset.cons/copy_assign.addressof.compile.pass.cpp b/libcxx/test/std/containers/associative/multiset/multiset.cons/copy_assign.addressof.compile.pass.cpp
new file mode 100644
index 000000000000..c91493ff0d62
--- /dev/null
+++ b/libcxx/test/std/containers/associative/multiset/multiset.cons/copy_assign.addressof.compile.pass.cpp
@@ -0,0 +1,26 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <set>
+
+// class multiset
+
+// multiset& operator=(const multiset& s);
+
+// Validate whether the container can be copy-assigned with an ADL-hijacking operator&
+
+#include <set>
+
+#include "test_macros.h"
+#include "operator_hijacker.h"
+
+void test() {
+  std::multiset<operator_hijacker> so;
+  std::multiset<operator_hijacker> s;
+  s = so;
+}

diff  --git a/libcxx/test/std/containers/associative/set/set.cons/copy_assign.addressof.compile.pass.cpp b/libcxx/test/std/containers/associative/set/set.cons/copy_assign.addressof.compile.pass.cpp
new file mode 100644
index 000000000000..e3677991a23d
--- /dev/null
+++ b/libcxx/test/std/containers/associative/set/set.cons/copy_assign.addressof.compile.pass.cpp
@@ -0,0 +1,26 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <set>
+
+// class set
+
+// set& operator=(const set& s);
+
+// Validate whether the container can be copy-assigned with an ADL-hijacking operator&
+
+#include <set>
+
+#include "test_macros.h"
+#include "operator_hijacker.h"
+
+void test() {
+  std::set<operator_hijacker> so;
+  std::set<operator_hijacker> s;
+  s = so;
+}

diff  --git a/libcxx/test/std/containers/container.adaptors/priority.queue/priqueue.cons/assign_copy.addressof.compile.pass.cpp b/libcxx/test/std/containers/container.adaptors/priority.queue/priqueue.cons/assign_copy.addressof.compile.pass.cpp
new file mode 100644
index 000000000000..57f287cd6f66
--- /dev/null
+++ b/libcxx/test/std/containers/container.adaptors/priority.queue/priqueue.cons/assign_copy.addressof.compile.pass.cpp
@@ -0,0 +1,24 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <queue>
+
+// priority_queue& operator=(const priority_queue&) = default;
+
+// Validate whether the container can be copy-assigned with an ADL-hijacking operator&
+
+#include <queue>
+
+#include "test_macros.h"
+#include "operator_hijacker.h"
+
+void test() {
+  std::priority_queue<operator_hijacker> pqo;
+  std::priority_queue<operator_hijacker> pq;
+  pq = pqo;
+}

diff  --git a/libcxx/test/std/containers/container.adaptors/queue/queue.defn/assign_copy.addressof.compile.pass.cpp b/libcxx/test/std/containers/container.adaptors/queue/queue.defn/assign_copy.addressof.compile.pass.cpp
new file mode 100644
index 000000000000..40e00ee24f6c
--- /dev/null
+++ b/libcxx/test/std/containers/container.adaptors/queue/queue.defn/assign_copy.addressof.compile.pass.cpp
@@ -0,0 +1,24 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <queue>
+
+// queue& operator=(const queue& q);
+
+// Validate whether the container can be copy-assigned with an ADL-hijacking operator&
+
+#include <queue>
+
+#include "test_macros.h"
+#include "operator_hijacker.h"
+
+void test() {
+  std::queue<operator_hijacker> qo;
+  std::queue<operator_hijacker> q;
+  q = qo;
+}

diff  --git a/libcxx/test/std/containers/sequences/array/array.cons/implicit_copy.addressof.compile.pass.cpp b/libcxx/test/std/containers/sequences/array/array.cons/implicit_copy.addressof.compile.pass.cpp
new file mode 100644
index 000000000000..44722648d452
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/array/array.cons/implicit_copy.addressof.compile.pass.cpp
@@ -0,0 +1,24 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <array>
+
+// implicitly generated array assignment operators
+
+// Validate whether the container can be copy-assigned with an ADL-hijacking operator&
+
+#include <array>
+
+#include "test_macros.h"
+#include "operator_hijacker.h"
+
+void test() {
+  std::array<operator_hijacker, 1> ao;
+  std::array<operator_hijacker, 1> a;
+  a = ao;
+}

diff  --git a/libcxx/test/std/containers/sequences/deque/deque.cons/move_assign.addressof.compile.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.cons/move_assign.addressof.compile.pass.cpp
new file mode 100644
index 000000000000..7b2326824bf0
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/deque/deque.cons/move_assign.addressof.compile.pass.cpp
@@ -0,0 +1,24 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <deque>
+
+// deque& operator=(deque&& c);
+
+// Validate whether the container can be copy-assigned with an ADL-hijacking operator&
+
+#include <deque>
+
+#include "test_macros.h"
+#include "operator_hijacker.h"
+
+void test() {
+  std::deque<operator_hijacker> dqo;
+  std::deque<operator_hijacker> dq;
+  dq = dqo;
+}

diff  --git a/libcxx/test/std/containers/sequences/forwardlist/forwardlist.cons/assign_copy.addressof.compile.pass.cpp b/libcxx/test/std/containers/sequences/forwardlist/forwardlist.cons/assign_copy.addressof.compile.pass.cpp
new file mode 100644
index 000000000000..ef2d38114d91
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/forwardlist/forwardlist.cons/assign_copy.addressof.compile.pass.cpp
@@ -0,0 +1,24 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <forward_list>
+
+// forward_list& operator=(const forward_list& x);
+
+// Validate whether the container can be copy-assigned with an ADL-hijacking operator&
+
+#include <forward_list>
+
+#include "test_macros.h"
+#include "operator_hijacker.h"
+
+void test() {
+  std::forward_list<operator_hijacker> lo;
+  std::forward_list<operator_hijacker> l;
+  l = lo;
+}

diff  --git a/libcxx/test/std/containers/sequences/list/list.cons/assign_copy.addressof.compile.pass.cpp b/libcxx/test/std/containers/sequences/list/list.cons/assign_copy.addressof.compile.pass.cpp
new file mode 100644
index 000000000000..f07e8cc69d73
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/list/list.cons/assign_copy.addressof.compile.pass.cpp
@@ -0,0 +1,27 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// Guard the debug iterators against ADL-hijacking.
+// XFAIL: LIBCXX-DEBUG-FIXME
+
+// <list>
+
+// list& operator=(const list& c);
+
+// Validate whether the container can be copy-assigned with an ADL-hijacking operator&
+
+#include <list>
+
+#include "test_macros.h"
+#include "operator_hijacker.h"
+
+void test() {
+  std::list<operator_hijacker> lo;
+  std::list<operator_hijacker> l;
+  l = lo;
+}

diff  --git a/libcxx/test/std/containers/sequences/vector/vector.cons/assign_copy.addressof.compile.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.cons/assign_copy.addressof.compile.pass.cpp
new file mode 100644
index 000000000000..ceecdfda3fa3
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/vector/vector.cons/assign_copy.addressof.compile.pass.cpp
@@ -0,0 +1,24 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// vector& operator=(const vector& c);
+
+// Validate whether the container can be copy-assigned with an ADL-hijacking operator&
+
+#include <vector>
+
+#include "test_macros.h"
+#include "operator_hijacker.h"
+
+void test() {
+  std::vector<operator_hijacker> vo;
+  std::vector<operator_hijacker> v;
+  v = vo;
+}

diff  --git a/libcxx/test/std/containers/unord/unord.map/unord.map.cnstr/assign_copy.addressof.compile.pass.cpp b/libcxx/test/std/containers/unord/unord.map/unord.map.cnstr/assign_copy.addressof.compile.pass.cpp
new file mode 100644
index 000000000000..49765c5f6345
--- /dev/null
+++ b/libcxx/test/std/containers/unord/unord.map/unord.map.cnstr/assign_copy.addressof.compile.pass.cpp
@@ -0,0 +1,38 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// Guard the debug iterators against ADL-hijacking.
+// XFAIL: LIBCXX-DEBUG-FIXME
+
+// <unordered_map>
+
+// template <class Key, class T, class Hash = hash<Key>, class Pred = equal_to<Key>,
+//           class Alloc = allocator<pair<const Key, T>>>
+// class unordered_map
+
+// unordered_map& operator=(const unordered_map& u);
+
+// Validate whether the container can be copy-assigned with an ADL-hijacking operator&
+
+#include <unordered_map>
+
+#include "test_macros.h"
+#include "operator_hijacker.h"
+
+void test() {
+  {
+    std::unordered_map<int, operator_hijacker> mo;
+    std::unordered_map<int, operator_hijacker> m;
+    m = mo;
+  }
+  {
+    std::unordered_map<operator_hijacker, int> mo;
+    std::unordered_map<operator_hijacker, int> m;
+    m = mo;
+  }
+}

diff  --git a/libcxx/test/std/containers/unord/unord.multimap/unord.multimap.cnstr/assign_copy.addressof.compile.pass.cpp b/libcxx/test/std/containers/unord/unord.multimap/unord.multimap.cnstr/assign_copy.addressof.compile.pass.cpp
new file mode 100644
index 000000000000..395c5d18ecac
--- /dev/null
+++ b/libcxx/test/std/containers/unord/unord.multimap/unord.multimap.cnstr/assign_copy.addressof.compile.pass.cpp
@@ -0,0 +1,38 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// Guard the debug iterators against ADL-hijacking.
+// XFAIL: LIBCXX-DEBUG-FIXME
+
+// <unordered_map>
+
+// template <class Key, class T, class Hash = hash<Key>, class Pred = equal_to<Key>,
+//           class Alloc = allocator<pair<const Key, T>>>
+// class unordered_multimap
+
+// unordered_multimap& operator=(const unordered_multimap& u);
+
+// Validate whether the container can be copy-assigned with an ADL-hijacking operator&
+
+#include <unordered_map>
+
+#include "test_macros.h"
+#include "operator_hijacker.h"
+
+void test() {
+  {
+    std::unordered_multimap<int, operator_hijacker> mo;
+    std::unordered_multimap<int, operator_hijacker> m;
+    m = mo;
+  }
+  {
+    std::unordered_multimap<operator_hijacker, int> mo;
+    std::unordered_multimap<operator_hijacker, int> m;
+    m = mo;
+  }
+}

diff  --git a/libcxx/test/std/containers/unord/unord.multiset/unord.multiset.cnstr/assign_copy.addressof.compile.pass.cpp b/libcxx/test/std/containers/unord/unord.multiset/unord.multiset.cnstr/assign_copy.addressof.compile.pass.cpp
new file mode 100644
index 000000000000..baf9fd286ade
--- /dev/null
+++ b/libcxx/test/std/containers/unord/unord.multiset/unord.multiset.cnstr/assign_copy.addressof.compile.pass.cpp
@@ -0,0 +1,31 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// Guard the debug iterators against ADL-hijacking.
+// XFAIL: LIBCXX-DEBUG-FIXME
+
+// <unordered_set>
+
+// template <class Value, class Hash = hash<Value>, class Pred = equal_to<Value>,
+//           class Alloc = allocator<Value>>
+// class unordered_multiset
+
+// unordered_multiset& operator=(const unordered_multiset& u);
+
+// Validate whether the container can be copy-assigned with an ADL-hijacking operator&
+
+#include <unordered_set>
+
+#include "test_macros.h"
+#include "operator_hijacker.h"
+
+void test() {
+  std::unordered_multiset<operator_hijacker> so;
+  std::unordered_multiset<operator_hijacker> s;
+  s = so;
+}

diff  --git a/libcxx/test/std/containers/unord/unord.set/unord.set.cnstr/assign_copy.addressof.compile.pass.cpp b/libcxx/test/std/containers/unord/unord.set/unord.set.cnstr/assign_copy.addressof.compile.pass.cpp
new file mode 100644
index 000000000000..d7a09028c476
--- /dev/null
+++ b/libcxx/test/std/containers/unord/unord.set/unord.set.cnstr/assign_copy.addressof.compile.pass.cpp
@@ -0,0 +1,31 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// Guard the debug iterators against ADL-hijacking.
+// XFAIL: LIBCXX-DEBUG-FIXME
+
+// <unordered_set>
+
+// template <class Value, class Hash = hash<Value>, class Pred = equal_to<Value>,
+//           class Alloc = allocator<Value>>
+// class unordered_set
+
+// unordered_set& operator=(const unordered_set& u);
+
+// Validate whether the container can be copy-assigned with an ADL-hijacking operator&
+
+#include <unordered_set>
+
+#include "test_macros.h"
+#include "operator_hijacker.h"
+
+void test() {
+  std::unordered_set<operator_hijacker> so;
+  std::unordered_set<operator_hijacker> s;
+  s = so;
+}

diff  --git a/libcxx/test/std/numerics/numarray/template.valarray/valarray.assign/value_assign.addressof.compile.pass.cpp b/libcxx/test/std/numerics/numarray/template.valarray/valarray.assign/value_assign.addressof.compile.pass.cpp
new file mode 100644
index 000000000000..c0359a8e9844
--- /dev/null
+++ b/libcxx/test/std/numerics/numarray/template.valarray/valarray.assign/value_assign.addressof.compile.pass.cpp
@@ -0,0 +1,26 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <valarray>
+
+// template<class T> class valarray;
+
+// valarray& operator=(const value_type& x);
+
+// Validate whether the container can be copy-assigned with an ADL-hijacking operator&
+
+#include <valarray>
+
+#include "test_macros.h"
+#include "operator_hijacker.h"
+
+void test() {
+  std::valarray<operator_hijacker> vo;
+  std::valarray<operator_hijacker> v;
+  v = vo;
+}

diff  --git a/libcxx/test/support/operator_hijacker.h b/libcxx/test/support/operator_hijacker.h
new file mode 100644
index 000000000000..34be330b056a
--- /dev/null
+++ b/libcxx/test/support/operator_hijacker.h
@@ -0,0 +1,39 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SUPPORT_OPERATOR_HIJACKER_H
+#define SUPPORT_OPERATOR_HIJACKER_H
+
+#include <cstddef>
+#include <functional>
+
+#include "test_macros.h"
+
+/// Helper struct to test ADL-hijacking in containers.
+///
+/// The class has some additional operations to be usable in all containers.
+struct operator_hijacker {
+  bool operator<(const operator_hijacker&) const { return true; }
+  bool operator==(const operator_hijacker&) const { return true; }
+
+  template <typename T>
+  friend void operator&(T&&) = delete;
+  template <class T, class U>
+  friend void operator,(T&&, U&&) = delete;
+  template <class T, class U>
+  friend void operator&&(T&&, U&&) = delete;
+  template <class T, class U>
+  friend void operator||(T&&, U&&) = delete;
+};
+
+template <>
+struct std::hash<operator_hijacker> {
+  size_t operator()(const operator_hijacker&) const { return 0; }
+};
+
+#endif // SUPPORT_OPERATOR_HIJACKER_H


        


More information about the libcxx-commits mailing list