Skip to content

Commit cab9616

Browse files
committed
[libc++] Use addressof in unordered_map.
This addresses the usage of `operator&` in `<unordered_map>`. (Note there are still more headers with the same issue.) Reviewed By: #libc, Quuxplusone, ldionne Differential Revision: https://reviews.llvm.org/D117393
1 parent f24fe96 commit cab9616

17 files changed

+527
-30
lines changed

libcxx/include/__hash_table

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -308,9 +308,9 @@ public:
308308
_LIBCPP_INLINE_VISIBILITY
309309
__hash_iterator& operator=(const __hash_iterator& __i)
310310
{
311-
if (this != &__i)
311+
if (this != _VSTD::addressof(__i))
312312
{
313-
__get_db()->__iterator_copy(this, &__i);
313+
__get_db()->__iterator_copy(this, _VSTD::addressof(__i));
314314
__node_ = __i.__node_;
315315
}
316316
return *this;
@@ -406,7 +406,7 @@ public:
406406
: __node_(__x.__node_)
407407
{
408408
#if _LIBCPP_DEBUG_LEVEL == 2
409-
__get_db()->__iterator_copy(this, &__x);
409+
__get_db()->__iterator_copy(this, _VSTD::addressof(__x));
410410
#endif
411411
}
412412

@@ -415,7 +415,7 @@ public:
415415
__hash_const_iterator(const __hash_const_iterator& __i)
416416
: __node_(__i.__node_)
417417
{
418-
__get_db()->__iterator_copy(this, &__i);
418+
__get_db()->__iterator_copy(this, _VSTD::addressof(__i));
419419
}
420420

421421
_LIBCPP_INLINE_VISIBILITY
@@ -427,9 +427,9 @@ public:
427427
_LIBCPP_INLINE_VISIBILITY
428428
__hash_const_iterator& operator=(const __hash_const_iterator& __i)
429429
{
430-
if (this != &__i)
430+
if (this != _VSTD::addressof(__i))
431431
{
432-
__get_db()->__iterator_copy(this, &__i);
432+
__get_db()->__iterator_copy(this, _VSTD::addressof(__i));
433433
__node_ = __i.__node_;
434434
}
435435
return *this;
@@ -523,7 +523,7 @@ public:
523523
__bucket_(__i.__bucket_),
524524
__bucket_count_(__i.__bucket_count_)
525525
{
526-
__get_db()->__iterator_copy(this, &__i);
526+
__get_db()->__iterator_copy(this, _VSTD::addressof(__i));
527527
}
528528

529529
_LIBCPP_INLINE_VISIBILITY
@@ -535,9 +535,9 @@ public:
535535
_LIBCPP_INLINE_VISIBILITY
536536
__hash_local_iterator& operator=(const __hash_local_iterator& __i)
537537
{
538-
if (this != &__i)
538+
if (this != _VSTD::addressof(__i))
539539
{
540-
__get_db()->__iterator_copy(this, &__i);
540+
__get_db()->__iterator_copy(this, _VSTD::addressof(__i));
541541
__node_ = __i.__node_;
542542
__bucket_ = __i.__bucket_;
543543
__bucket_count_ = __i.__bucket_count_;
@@ -655,7 +655,7 @@ public:
655655
__bucket_count_(__x.__bucket_count_)
656656
{
657657
#if _LIBCPP_DEBUG_LEVEL == 2
658-
__get_db()->__iterator_copy(this, &__x);
658+
__get_db()->__iterator_copy(this, _VSTD::addressof(__x));
659659
#endif
660660
}
661661

@@ -666,7 +666,7 @@ public:
666666
__bucket_(__i.__bucket_),
667667
__bucket_count_(__i.__bucket_count_)
668668
{
669-
__get_db()->__iterator_copy(this, &__i);
669+
__get_db()->__iterator_copy(this, _VSTD::addressof(__i));
670670
}
671671

672672
_LIBCPP_INLINE_VISIBILITY
@@ -678,9 +678,9 @@ public:
678678
_LIBCPP_INLINE_VISIBILITY
679679
__hash_const_local_iterator& operator=(const __hash_const_local_iterator& __i)
680680
{
681-
if (this != &__i)
681+
if (this != _VSTD::addressof(__i))
682682
{
683-
__get_db()->__iterator_copy(this, &__i);
683+
__get_db()->__iterator_copy(this, _VSTD::addressof(__i));
684684
__node_ = __i.__node_;
685685
__bucket_ = __i.__bucket_;
686686
__bucket_count_ = __i.__bucket_count_;
@@ -1615,7 +1615,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign(
16151615
__u.size() = 0;
16161616
}
16171617
#if _LIBCPP_DEBUG_LEVEL == 2
1618-
__get_db()->swap(this, &__u);
1618+
__get_db()->swap(this, _VSTD::addressof(__u));
16191619
#endif
16201620
}
16211621

@@ -2021,7 +2021,7 @@ typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
20212021
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi(
20222022
const_iterator __p, __node_pointer __cp)
20232023
{
2024-
_LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this,
2024+
_LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__p)) == this,
20252025
"unordered container::emplace_hint(const_iterator, args...) called with an iterator not"
20262026
" referring to this unordered container");
20272027
if (__p != end() && key_eq()(*__p, __cp->__value_))
@@ -2148,7 +2148,7 @@ typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
21482148
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_hint_multi(
21492149
const_iterator __p, _Args&&... __args)
21502150
{
2151-
_LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this,
2151+
_LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__p)) == this,
21522152
"unordered container::emplace_hint(const_iterator, args...) called with an iterator not"
21532153
" referring to this unordered container");
21542154
__node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
@@ -2472,7 +2472,7 @@ typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
24722472
__hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __p)
24732473
{
24742474
__next_pointer __np = __p.__node_;
2475-
_LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this,
2475+
_LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__p)) == this,
24762476
"unordered container erase(iterator) called with an iterator not"
24772477
" referring to this container");
24782478
_LIBCPP_DEBUG_ASSERT(__p != end(),
@@ -2492,10 +2492,10 @@ typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
24922492
__hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __first,
24932493
const_iterator __last)
24942494
{
2495-
_LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(&__first) == this,
2495+
_LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__first)) == this,
24962496
"unordered container::erase(iterator, iterator) called with an iterator not"
24972497
" referring to this container");
2498-
_LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(&__last) == this,
2498+
_LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__last)) == this,
24992499
"unordered container::erase(iterator, iterator) called with an iterator not"
25002500
" referring to this container");
25012501
for (const_iterator __p = __first; __first != __last; __p = __first)
@@ -2727,7 +2727,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::swap(__hash_table& __u)
27272727
__u.__bucket_list_[__constrain_hash(__u.__p1_.first().__next_->__hash(), __u.bucket_count())] =
27282728
__u.__p1_.first().__ptr();
27292729
#if _LIBCPP_DEBUG_LEVEL == 2
2730-
__get_db()->swap(this, &__u);
2730+
__get_db()->swap(this, _VSTD::addressof(__u));
27312731
#endif
27322732
}
27332733

libcxx/include/unordered_map

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,7 @@ template <class Key, class T, class Hash, class Pred, class Alloc>
519519
#include <__functional/is_transparent.h>
520520
#include <__hash_table>
521521
#include <__iterator/iterator_traits.h>
522+
#include <__memory/addressof.h>
522523
#include <__node_handle>
523524
#include <__utility/forward.h>
524525
#include <compare>
@@ -1186,7 +1187,7 @@ public:
11861187
{return __table_.__insert_unique(__x);}
11871188

11881189
iterator insert(const_iterator __p, const value_type& __x) {
1189-
_LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this,
1190+
_LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i()_VSTD::addressof(__p) == this,
11901191
"unordered_map::insert(const_iterator, const value_type&) called with an iterator not "
11911192
"referring to this unordered_map");
11921193
((void)__p);
@@ -1207,7 +1208,7 @@ public:
12071208
{return __table_.__insert_unique(_VSTD::move(__x));}
12081209

12091210
iterator insert(const_iterator __p, value_type&& __x) {
1210-
_LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this,
1211+
_LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__p)) == this,
12111212
"unordered_map::insert(const_iterator, const value_type&) called with an iterator not"
12121213
" referring to this unordered_map");
12131214
((void)__p);
@@ -1225,7 +1226,7 @@ public:
12251226
_LIBCPP_INLINE_VISIBILITY
12261227
iterator insert(const_iterator __p, _Pp&& __x)
12271228
{
1228-
_LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this,
1229+
_LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__p)) == this,
12291230
"unordered_map::insert(const_iterator, value_type&&) called with an iterator not"
12301231
" referring to this unordered_map");
12311232
((void)__p);
@@ -1241,7 +1242,7 @@ public:
12411242
template <class... _Args>
12421243
_LIBCPP_INLINE_VISIBILITY
12431244
iterator emplace_hint(const_iterator __p, _Args&&... __args) {
1244-
_LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this,
1245+
_LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__p)) == this,
12451246
"unordered_map::emplace_hint(const_iterator, args...) called with an iterator not"
12461247
" referring to this unordered_map");
12471248
((void)__p);
@@ -1273,7 +1274,7 @@ public:
12731274
_LIBCPP_INLINE_VISIBILITY
12741275
iterator try_emplace(const_iterator __h, const key_type& __k, _Args&&... __args)
12751276
{
1276-
_LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(&__h) == this,
1277+
_LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__h)) == this,
12771278
"unordered_map::try_emplace(const_iterator, key, args...) called with an iterator not"
12781279
" referring to this unordered_map");
12791280
((void)__h);
@@ -1284,7 +1285,7 @@ public:
12841285
_LIBCPP_INLINE_VISIBILITY
12851286
iterator try_emplace(const_iterator __h, key_type&& __k, _Args&&... __args)
12861287
{
1287-
_LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(&__h) == this,
1288+
_LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i()_VSTD::addressof(__h) == this,
12881289
"unordered_map::try_emplace(const_iterator, key, args...) called with an iterator not"
12891290
" referring to this unordered_map");
12901291
((void)__h);
@@ -1692,7 +1693,7 @@ unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map(
16921693
{
16931694
_VSTD::__debug_db_insert_c(this);
16941695
#if _LIBCPP_DEBUG_LEVEL == 2
1695-
__get_db()->swap(this, &__u);
1696+
__get_db()->swap(this, _VSTD::addressof(__u));
16961697
#endif
16971698
}
16981699

@@ -1712,7 +1713,7 @@ unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map(
17121713
}
17131714
#if _LIBCPP_DEBUG_LEVEL == 2
17141715
else
1715-
__get_db()->swap(this, &__u);
1716+
__get_db()->swap(this, _VSTD::addressof(__u));
17161717
#endif
17171718
}
17181719

@@ -2468,7 +2469,7 @@ unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_multimap(
24682469
{
24692470
_VSTD::__debug_db_insert_c(this);
24702471
#if _LIBCPP_DEBUG_LEVEL == 2
2471-
__get_db()->swap(this, &__u);
2472+
__get_db()->swap(this, _VSTD::addressof(__u));
24722473
#endif
24732474
}
24742475

@@ -2489,7 +2490,7 @@ unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_multimap(
24892490
}
24902491
#if _LIBCPP_DEBUG_LEVEL == 2
24912492
else
2492-
__get_db()->swap(this, &__u);
2493+
__get_db()->swap(this, _VSTD::addressof(__u));
24932494
#endif
24942495
}
24952496

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// <unordered_map>
10+
11+
// template <class Key, class T, class Hash = hash<Key>, class Pred = equal_to<Key>,
12+
// class Alloc = allocator<pair<const Key, T>>>
13+
// class unordered_map
14+
15+
// Validate the constructors of the (const)(_local)_iterator classes to be
16+
// properly guarded against ADL-hijacking operator&.
17+
18+
#include <unordered_map>
19+
20+
#include "test_macros.h"
21+
#include "operator_hijacker.h"
22+
23+
template <class ToIterator, class FromIterator>
24+
void test() {
25+
FromIterator from;
26+
ToIterator copy(from);
27+
copy = from;
28+
29+
ToIterator move(std::move(from));
30+
from = FromIterator();
31+
move = std::move(from);
32+
}
33+
34+
void test() {
35+
{
36+
using I = std::unordered_map<operator_hijacker, operator_hijacker>::iterator;
37+
using CI = std::unordered_map<operator_hijacker, operator_hijacker>::const_iterator;
38+
test<I, I>();
39+
test<CI, I>();
40+
test<CI, CI>();
41+
}
42+
{
43+
using IL = std::unordered_map<operator_hijacker, operator_hijacker>::local_iterator;
44+
using CIL = std::unordered_map<operator_hijacker, operator_hijacker>::const_local_iterator;
45+
test<IL, IL>();
46+
test<CIL, IL>();
47+
test<CIL, CIL>();
48+
}
49+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// UNSUPPORTED: c++03
10+
11+
// <unordered_map>
12+
13+
// template <class Key, class T, class Hash = hash<Key>, class Pred = equal_to<Key>,
14+
// class Alloc = allocator<pair<const Key, T>>>
15+
// class unordered_map
16+
17+
// unordered_map& operator=(unordered_map&&)
18+
// noexcept(
19+
// allocator_type::propagate_on_container_move_assignment::value &&
20+
// is_nothrow_move_assignable<allocator_type>::value &&
21+
// is_nothrow_move_assignable<hasher>::value &&
22+
// is_nothrow_move_assignable<key_equal>::value);
23+
24+
// Validate whether the container can be move-assigned with an ADL-hijacking operator&
25+
26+
#include <unordered_map>
27+
28+
#include "test_macros.h"
29+
#include "operator_hijacker.h"
30+
31+
void test() {
32+
{
33+
std::unordered_map<int, operator_hijacker> mo;
34+
std::unordered_map<int, operator_hijacker> m;
35+
m = std::move(mo);
36+
}
37+
{
38+
std::unordered_map<operator_hijacker, int> mo;
39+
std::unordered_map<operator_hijacker, int> m;
40+
m = std::move(mo);
41+
}
42+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// UNSUPPORTED: c++03
10+
11+
// <unordered_map>
12+
13+
// template <class Key, class T, class Hash = hash<Key>, class Pred = equal_to<Key>,
14+
// class Alloc = allocator<pair<const Key, T>>>
15+
// class unordered_map
16+
17+
// unordered_map(unordered_map&& u)
18+
// noexcept(
19+
// is_nothrow_move_constructible<hasher>::value &&
20+
// is_nothrow_move_constructible<key_equal>::value &&
21+
// is_nothrow_move_constructible<allocator_type>::value);
22+
23+
// Validate whether the operation properly guards against ADL-hijacking operator&
24+
25+
#include <unordered_map>
26+
27+
#include "test_macros.h"
28+
#include "operator_hijacker.h"
29+
30+
void test() {
31+
std::unordered_map<operator_hijacker, operator_hijacker> mo;
32+
std::unordered_map<operator_hijacker, operator_hijacker> m(std::move(mo));
33+
}

0 commit comments

Comments
 (0)