Skip to content

Commit 5111324

Browse files
committed
[libc++][unordered_map] Applied [[nodiscard]]
[[nodiscard]] should be applied to functions where discarding the return value is most likely a correctness issue. - https://libcxx.llvm.org/CodingGuidelines.html - https://wg21.link/unord.multimap
1 parent f5742c4 commit 5111324

File tree

4 files changed

+150
-54
lines changed

4 files changed

+150
-54
lines changed

libcxx/include/unordered_map

Lines changed: 53 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1034,20 +1034,20 @@ public:
10341034
_LIBCPP_HIDE_FROM_ABI unordered_map& operator=(initializer_list<value_type> __il);
10351035
# endif // _LIBCPP_CXX03_LANG
10361036

1037-
_LIBCPP_HIDE_FROM_ABI allocator_type get_allocator() const _NOEXCEPT {
1037+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI allocator_type get_allocator() const _NOEXCEPT {
10381038
return allocator_type(__table_.__node_alloc());
10391039
}
10401040

10411041
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT { return __table_.size() == 0; }
1042-
_LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT { return __table_.size(); }
1043-
_LIBCPP_HIDE_FROM_ABI size_type max_size() const _NOEXCEPT { return __table_.max_size(); }
1042+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT { return __table_.size(); }
1043+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_type max_size() const _NOEXCEPT { return __table_.max_size(); }
10441044

1045-
_LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT { return __table_.begin(); }
1046-
_LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT { return __table_.end(); }
1047-
_LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT { return __table_.begin(); }
1048-
_LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT { return __table_.end(); }
1049-
_LIBCPP_HIDE_FROM_ABI const_iterator cbegin() const _NOEXCEPT { return __table_.begin(); }
1050-
_LIBCPP_HIDE_FROM_ABI const_iterator cend() const _NOEXCEPT { return __table_.end(); }
1045+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT { return __table_.begin(); }
1046+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT { return __table_.end(); }
1047+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT { return __table_.begin(); }
1048+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT { return __table_.end(); }
1049+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator cbegin() const _NOEXCEPT { return __table_.begin(); }
1050+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator cend() const _NOEXCEPT { return __table_.end(); }
10511051

10521052
_LIBCPP_HIDE_FROM_ABI pair<iterator, bool> insert(const value_type& __x) { return __table_.__emplace_unique(__x); }
10531053

@@ -1171,10 +1171,10 @@ public:
11711171
"node_type with incompatible allocator passed to unordered_map::insert()");
11721172
return __table_.template __node_handle_insert_unique<node_type>(__hint.__i_, std::move(__nh));
11731173
}
1174-
_LIBCPP_HIDE_FROM_ABI node_type extract(key_type const& __key) {
1174+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI node_type extract(key_type const& __key) {
11751175
return __table_.template __node_handle_extract<node_type>(__key);
11761176
}
1177-
_LIBCPP_HIDE_FROM_ABI node_type extract(const_iterator __it) {
1177+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI node_type extract(const_iterator __it) {
11781178
return __table_.template __node_handle_extract<node_type>(__it.__i_);
11791179
}
11801180

@@ -1208,79 +1208,91 @@ public:
12081208
__table_.swap(__u.__table_);
12091209
}
12101210

1211-
_LIBCPP_HIDE_FROM_ABI hasher hash_function() const { return __table_.hash_function().hash_function(); }
1212-
_LIBCPP_HIDE_FROM_ABI key_equal key_eq() const { return __table_.key_eq().key_eq(); }
1211+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI hasher hash_function() const {
1212+
return __table_.hash_function().hash_function();
1213+
}
1214+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI key_equal key_eq() const { return __table_.key_eq().key_eq(); }
12131215

1214-
_LIBCPP_HIDE_FROM_ABI iterator find(const key_type& __k) { return __table_.find(__k); }
1215-
_LIBCPP_HIDE_FROM_ABI const_iterator find(const key_type& __k) const { return __table_.find(__k); }
1216+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iterator find(const key_type& __k) { return __table_.find(__k); }
1217+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator find(const key_type& __k) const { return __table_.find(__k); }
12161218
# if _LIBCPP_STD_VER >= 20
12171219
template <class _K2, enable_if_t<__is_transparent_v<hasher, _K2> && __is_transparent_v<key_equal, _K2>>* = nullptr>
1218-
_LIBCPP_HIDE_FROM_ABI iterator find(const _K2& __k) {
1220+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI iterator find(const _K2& __k) {
12191221
return __table_.find(__k);
12201222
}
12211223
template <class _K2, enable_if_t<__is_transparent_v<hasher, _K2> && __is_transparent_v<key_equal, _K2>>* = nullptr>
1222-
_LIBCPP_HIDE_FROM_ABI const_iterator find(const _K2& __k) const {
1224+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI const_iterator find(const _K2& __k) const {
12231225
return __table_.find(__k);
12241226
}
12251227
# endif // _LIBCPP_STD_VER >= 20
12261228

1227-
_LIBCPP_HIDE_FROM_ABI size_type count(const key_type& __k) const { return __table_.__count_unique(__k); }
1229+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_type count(const key_type& __k) const {
1230+
return __table_.__count_unique(__k);
1231+
}
12281232
# if _LIBCPP_STD_VER >= 20
12291233
template <class _K2, enable_if_t<__is_transparent_v<hasher, _K2> && __is_transparent_v<key_equal, _K2>>* = nullptr>
1230-
_LIBCPP_HIDE_FROM_ABI size_type count(const _K2& __k) const {
1234+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI size_type count(const _K2& __k) const {
12311235
return __table_.__count_unique(__k);
12321236
}
12331237
# endif // _LIBCPP_STD_VER >= 20
12341238

12351239
# if _LIBCPP_STD_VER >= 20
1236-
_LIBCPP_HIDE_FROM_ABI bool contains(const key_type& __k) const { return find(__k) != end(); }
1240+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool contains(const key_type& __k) const { return find(__k) != end(); }
12371241

12381242
template <class _K2, enable_if_t<__is_transparent_v<hasher, _K2> && __is_transparent_v<key_equal, _K2>>* = nullptr>
1239-
_LIBCPP_HIDE_FROM_ABI bool contains(const _K2& __k) const {
1243+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool contains(const _K2& __k) const {
12401244
return find(__k) != end();
12411245
}
12421246
# endif // _LIBCPP_STD_VER >= 20
12431247

1244-
_LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> equal_range(const key_type& __k) {
1248+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> equal_range(const key_type& __k) {
12451249
return __table_.__equal_range_unique(__k);
12461250
}
1247-
_LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> equal_range(const key_type& __k) const {
1251+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> equal_range(const key_type& __k) const {
12481252
return __table_.__equal_range_unique(__k);
12491253
}
12501254
# if _LIBCPP_STD_VER >= 20
12511255
template <class _K2, enable_if_t<__is_transparent_v<hasher, _K2> && __is_transparent_v<key_equal, _K2>>* = nullptr>
1252-
_LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> equal_range(const _K2& __k) {
1256+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> equal_range(const _K2& __k) {
12531257
return __table_.__equal_range_unique(__k);
12541258
}
12551259
template <class _K2, enable_if_t<__is_transparent_v<hasher, _K2> && __is_transparent_v<key_equal, _K2>>* = nullptr>
1256-
_LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> equal_range(const _K2& __k) const {
1260+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> equal_range(const _K2& __k) const {
12571261
return __table_.__equal_range_unique(__k);
12581262
}
12591263
# endif // _LIBCPP_STD_VER >= 20
12601264

1261-
_LIBCPP_HIDE_FROM_ABI mapped_type& operator[](const key_type& __k);
1265+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI mapped_type& operator[](const key_type& __k);
12621266
# ifndef _LIBCPP_CXX03_LANG
1263-
_LIBCPP_HIDE_FROM_ABI mapped_type& operator[](key_type&& __k);
1267+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI mapped_type& operator[](key_type&& __k);
12641268
# endif
12651269

1266-
_LIBCPP_HIDE_FROM_ABI mapped_type& at(const key_type& __k);
1267-
_LIBCPP_HIDE_FROM_ABI const mapped_type& at(const key_type& __k) const;
1270+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI mapped_type& at(const key_type& __k);
1271+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const mapped_type& at(const key_type& __k) const;
12681272

1269-
_LIBCPP_HIDE_FROM_ABI size_type bucket_count() const _NOEXCEPT { return __table_.bucket_count(); }
1270-
_LIBCPP_HIDE_FROM_ABI size_type max_bucket_count() const _NOEXCEPT { return __table_.max_bucket_count(); }
1273+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_type bucket_count() const _NOEXCEPT { return __table_.bucket_count(); }
1274+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_type max_bucket_count() const _NOEXCEPT {
1275+
return __table_.max_bucket_count();
1276+
}
12711277

1272-
_LIBCPP_HIDE_FROM_ABI size_type bucket_size(size_type __n) const { return __table_.bucket_size(__n); }
1273-
_LIBCPP_HIDE_FROM_ABI size_type bucket(const key_type& __k) const { return __table_.bucket(__k); }
1278+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_type bucket_size(size_type __n) const {
1279+
return __table_.bucket_size(__n);
1280+
}
1281+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_type bucket(const key_type& __k) const { return __table_.bucket(__k); }
12741282

1275-
_LIBCPP_HIDE_FROM_ABI local_iterator begin(size_type __n) { return __table_.begin(__n); }
1276-
_LIBCPP_HIDE_FROM_ABI local_iterator end(size_type __n) { return __table_.end(__n); }
1277-
_LIBCPP_HIDE_FROM_ABI const_local_iterator begin(size_type __n) const { return __table_.cbegin(__n); }
1278-
_LIBCPP_HIDE_FROM_ABI const_local_iterator end(size_type __n) const { return __table_.cend(__n); }
1279-
_LIBCPP_HIDE_FROM_ABI const_local_iterator cbegin(size_type __n) const { return __table_.cbegin(__n); }
1280-
_LIBCPP_HIDE_FROM_ABI const_local_iterator cend(size_type __n) const { return __table_.cend(__n); }
1283+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI local_iterator begin(size_type __n) { return __table_.begin(__n); }
1284+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI local_iterator end(size_type __n) { return __table_.end(__n); }
1285+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_local_iterator begin(size_type __n) const {
1286+
return __table_.cbegin(__n);
1287+
}
1288+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_local_iterator end(size_type __n) const { return __table_.cend(__n); }
1289+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_local_iterator cbegin(size_type __n) const {
1290+
return __table_.cbegin(__n);
1291+
}
1292+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_local_iterator cend(size_type __n) const { return __table_.cend(__n); }
12811293

1282-
_LIBCPP_HIDE_FROM_ABI float load_factor() const _NOEXCEPT { return __table_.load_factor(); }
1283-
_LIBCPP_HIDE_FROM_ABI float max_load_factor() const _NOEXCEPT { return __table_.max_load_factor(); }
1294+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI float load_factor() const _NOEXCEPT { return __table_.load_factor(); }
1295+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI float max_load_factor() const _NOEXCEPT { return __table_.max_load_factor(); }
12841296
_LIBCPP_HIDE_FROM_ABI void max_load_factor(float __mlf) { __table_.max_load_factor(__mlf); }
12851297
_LIBCPP_HIDE_FROM_ABI void rehash(size_type __n) { __table_.__rehash_unique(__n); }
12861298
_LIBCPP_HIDE_FROM_ABI void reserve(size_type __n) { __table_.__reserve_unique(__n); }

libcxx/test/libcxx/containers/unord/unord.map/at.abort.pass.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,6 @@
2727
int main(int, char**) {
2828
std::signal(SIGABRT, [](int) { std::_Exit(EXIT_SUCCESS); });
2929
std::unordered_map<int, int> map;
30-
map.at(1);
30+
(void)map.at(1);
3131
return EXIT_FAILURE;
3232
}

libcxx/test/libcxx/containers/unord/unord.map/at.const.abort.pass.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,6 @@
2727
int main(int, char**) {
2828
std::signal(SIGABRT, [](int) { std::_Exit(EXIT_SUCCESS); });
2929
std::unordered_map<int, int> const map;
30-
map.at(1);
30+
(void)map.at(1);
3131
return EXIT_FAILURE;
3232
}

libcxx/test/libcxx/diagnostics/unordered_map.nodiscard.verify.cpp

Lines changed: 95 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,104 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9-
// UNSUPPORTED: c++03
9+
// REQUIRES: std-at-least-c++11
1010

11-
// check that <unordered_map> functions are marked [[nodiscard]]
12-
13-
// clang-format off
11+
// Check that functions are marked [[nodiscard]]
1412

1513
#include <unordered_map>
14+
#include <utility>
1615

17-
void unordered_map_test() {
18-
std::unordered_map<int, int> unordered_map;
19-
unordered_map.empty(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
20-
}
16+
#include "test_macros.h"
17+
18+
struct TransparentKey {};
19+
20+
struct StoredKey {
21+
friend bool operator==(StoredKey const&, StoredKey const&) { return true; }
22+
friend bool operator==(StoredKey const&, TransparentKey const&) { return true; }
23+
};
24+
25+
struct TransparentKeyHash {
26+
using is_transparent = void;
27+
28+
constexpr std::size_t operator()(TransparentKey const&) const { return 0; }
29+
constexpr std::size_t operator()(StoredKey const&) const { return 0; }
30+
};
31+
32+
void test() {
33+
std::unordered_map<int, int> m;
34+
const std::unordered_map<int, int> cm;
35+
36+
m.get_allocator(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
37+
38+
m.empty(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
39+
m.size(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
40+
m.max_size(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
41+
42+
m.begin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
43+
m.end(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
44+
cm.begin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
45+
cm.end(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
46+
cm.cbegin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
47+
cm.cend(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
48+
49+
int key = 0;
50+
51+
#if TEST_STD_VER >= 17
52+
m.extract(0); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
53+
m.extract(m.begin()); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
54+
#endif
55+
56+
m.hash_function(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
57+
m.key_eq(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
58+
59+
m.find(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
60+
cm.find(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
61+
#if TEST_STD_VER >= 20
62+
std::unordered_map<StoredKey, int, TransparentKeyHash, std::equal_to<>> tm;
63+
const std::unordered_map<StoredKey, int, TransparentKeyHash, std::equal_to<>> ctm;
64+
65+
TransparentKey tkey;
66+
67+
tm.find(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
68+
ctm.find(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
69+
#endif
70+
71+
#if TEST_STD_VER >= 20
72+
m.count(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
73+
cm.count(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
74+
75+
tm.contains(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
76+
ctm.contains(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
77+
#endif
78+
79+
m.equal_range(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
80+
cm.equal_range(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
81+
#if TEST_STD_VER >= 20
82+
tm.equal_range(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
83+
ctm.equal_range(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
84+
#endif
85+
86+
m[key]; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
87+
m[std::move(key)]; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
88+
89+
m.at(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
90+
cm.at(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
91+
92+
m.bucket_count(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
93+
m.max_bucket_count(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
94+
95+
int size = 0;
96+
97+
m.bucket_size(size); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
98+
m.bucket(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
99+
100+
m.begin(size); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
101+
m.end(size); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
102+
cm.begin(size); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
103+
cm.end(size); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
104+
cm.cbegin(size); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
105+
cm.cend(size); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
21106

22-
void unordered_multimap_test() {
23-
std::unordered_multimap<int, int> unordered_multimap;
24-
unordered_multimap.empty(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
107+
m.load_factor(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
108+
m.max_load_factor(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
25109
}

0 commit comments

Comments
 (0)