Skip to content

Commit a5b7c42

Browse files
authored
[libc++][unordered_multimap] Applied [[nodiscard]] (#171659)
`[[nodiscard]]` should be applied to functions where discarding the return value is most likely a correctness issue. - https://libcxx.llvm.org/CodingGuidelines.htm - https://wg21.link/unord.multimap
1 parent ffaa6f2 commit a5b7c42

File tree

2 files changed

+150
-37
lines changed

2 files changed

+150
-37
lines changed

libcxx/include/unordered_map

Lines changed: 49 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1810,20 +1810,20 @@ public:
18101810
_LIBCPP_HIDE_FROM_ABI unordered_multimap& operator=(initializer_list<value_type> __il);
18111811
# endif // _LIBCPP_CXX03_LANG
18121812

1813-
_LIBCPP_HIDE_FROM_ABI allocator_type get_allocator() const _NOEXCEPT {
1813+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI allocator_type get_allocator() const _NOEXCEPT {
18141814
return allocator_type(__table_.__node_alloc());
18151815
}
18161816

18171817
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT { return __table_.size() == 0; }
1818-
_LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT { return __table_.size(); }
1819-
_LIBCPP_HIDE_FROM_ABI size_type max_size() const _NOEXCEPT { return __table_.max_size(); }
1818+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT { return __table_.size(); }
1819+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_type max_size() const _NOEXCEPT { return __table_.max_size(); }
18201820

1821-
_LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT { return __table_.begin(); }
1822-
_LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT { return __table_.end(); }
1823-
_LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT { return __table_.begin(); }
1824-
_LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT { return __table_.end(); }
1825-
_LIBCPP_HIDE_FROM_ABI const_iterator cbegin() const _NOEXCEPT { return __table_.begin(); }
1826-
_LIBCPP_HIDE_FROM_ABI const_iterator cend() const _NOEXCEPT { return __table_.end(); }
1821+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT { return __table_.begin(); }
1822+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT { return __table_.end(); }
1823+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT { return __table_.begin(); }
1824+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT { return __table_.end(); }
1825+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator cbegin() const _NOEXCEPT { return __table_.begin(); }
1826+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator cend() const _NOEXCEPT { return __table_.end(); }
18271827

18281828
_LIBCPP_HIDE_FROM_ABI iterator insert(const value_type& __x) { return __table_.__emplace_multi(__x); }
18291829

@@ -1891,10 +1891,10 @@ public:
18911891
"node_type with incompatible allocator passed to unordered_multimap::insert()");
18921892
return __table_.template __node_handle_insert_multi<node_type>(__hint.__i_, std::move(__nh));
18931893
}
1894-
_LIBCPP_HIDE_FROM_ABI node_type extract(key_type const& __key) {
1894+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI node_type extract(key_type const& __key) {
18951895
return __table_.template __node_handle_extract<node_type>(__key);
18961896
}
1897-
_LIBCPP_HIDE_FROM_ABI node_type extract(const_iterator __it) {
1897+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI node_type extract(const_iterator __it) {
18981898
return __table_.template __node_handle_extract<node_type>(__it.__i_);
18991899
}
19001900

@@ -1928,71 +1928,83 @@ public:
19281928
__table_.swap(__u.__table_);
19291929
}
19301930

1931-
_LIBCPP_HIDE_FROM_ABI hasher hash_function() const { return __table_.hash_function().hash_function(); }
1932-
_LIBCPP_HIDE_FROM_ABI key_equal key_eq() const { return __table_.key_eq().key_eq(); }
1931+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI hasher hash_function() const {
1932+
return __table_.hash_function().hash_function();
1933+
}
1934+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI key_equal key_eq() const { return __table_.key_eq().key_eq(); }
19331935

1934-
_LIBCPP_HIDE_FROM_ABI iterator find(const key_type& __k) { return __table_.find(__k); }
1935-
_LIBCPP_HIDE_FROM_ABI const_iterator find(const key_type& __k) const { return __table_.find(__k); }
1936+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iterator find(const key_type& __k) { return __table_.find(__k); }
1937+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator find(const key_type& __k) const { return __table_.find(__k); }
19361938
# if _LIBCPP_STD_VER >= 20
19371939
template <class _K2, enable_if_t<__is_transparent_v<hasher, _K2> && __is_transparent_v<key_equal, _K2>>* = nullptr>
1938-
_LIBCPP_HIDE_FROM_ABI iterator find(const _K2& __k) {
1940+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iterator find(const _K2& __k) {
19391941
return __table_.find(__k);
19401942
}
19411943
template <class _K2, enable_if_t<__is_transparent_v<hasher, _K2> && __is_transparent_v<key_equal, _K2>>* = nullptr>
1942-
_LIBCPP_HIDE_FROM_ABI const_iterator find(const _K2& __k) const {
1944+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator find(const _K2& __k) const {
19431945
return __table_.find(__k);
19441946
}
19451947
# endif // _LIBCPP_STD_VER >= 20
19461948

1947-
_LIBCPP_HIDE_FROM_ABI size_type count(const key_type& __k) const { return __table_.__count_multi(__k); }
1949+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_type count(const key_type& __k) const {
1950+
return __table_.__count_multi(__k);
1951+
}
19481952
# if _LIBCPP_STD_VER >= 20
19491953
template <class _K2, enable_if_t<__is_transparent_v<hasher, _K2> && __is_transparent_v<key_equal, _K2>>* = nullptr>
1950-
_LIBCPP_HIDE_FROM_ABI size_type count(const _K2& __k) const {
1954+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_type count(const _K2& __k) const {
19511955
return __table_.__count_multi(__k);
19521956
}
19531957
# endif // _LIBCPP_STD_VER >= 20
19541958

19551959
# if _LIBCPP_STD_VER >= 20
1956-
_LIBCPP_HIDE_FROM_ABI bool contains(const key_type& __k) const { return find(__k) != end(); }
1960+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool contains(const key_type& __k) const { return find(__k) != end(); }
19571961

19581962
template <class _K2, enable_if_t<__is_transparent_v<hasher, _K2> && __is_transparent_v<key_equal, _K2>>* = nullptr>
1959-
_LIBCPP_HIDE_FROM_ABI bool contains(const _K2& __k) const {
1963+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool contains(const _K2& __k) const {
19601964
return find(__k) != end();
19611965
}
19621966
# endif // _LIBCPP_STD_VER >= 20
19631967

1964-
_LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> equal_range(const key_type& __k) {
1968+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> equal_range(const key_type& __k) {
19651969
return __table_.__equal_range_multi(__k);
19661970
}
1967-
_LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> equal_range(const key_type& __k) const {
1971+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> equal_range(const key_type& __k) const {
19681972
return __table_.__equal_range_multi(__k);
19691973
}
19701974
# if _LIBCPP_STD_VER >= 20
19711975
template <class _K2, enable_if_t<__is_transparent_v<hasher, _K2> && __is_transparent_v<key_equal, _K2>>* = nullptr>
1972-
_LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> equal_range(const _K2& __k) {
1976+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> equal_range(const _K2& __k) {
19731977
return __table_.__equal_range_multi(__k);
19741978
}
19751979
template <class _K2, enable_if_t<__is_transparent_v<hasher, _K2> && __is_transparent_v<key_equal, _K2>>* = nullptr>
1976-
_LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> equal_range(const _K2& __k) const {
1980+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> equal_range(const _K2& __k) const {
19771981
return __table_.__equal_range_multi(__k);
19781982
}
19791983
# endif // _LIBCPP_STD_VER >= 20
19801984

1981-
_LIBCPP_HIDE_FROM_ABI size_type bucket_count() const _NOEXCEPT { return __table_.bucket_count(); }
1982-
_LIBCPP_HIDE_FROM_ABI size_type max_bucket_count() const _NOEXCEPT { return __table_.max_bucket_count(); }
1985+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_type bucket_count() const _NOEXCEPT { return __table_.bucket_count(); }
1986+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_type max_bucket_count() const _NOEXCEPT {
1987+
return __table_.max_bucket_count();
1988+
}
19831989

1984-
_LIBCPP_HIDE_FROM_ABI size_type bucket_size(size_type __n) const { return __table_.bucket_size(__n); }
1985-
_LIBCPP_HIDE_FROM_ABI size_type bucket(const key_type& __k) const { return __table_.bucket(__k); }
1990+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_type bucket_size(size_type __n) const {
1991+
return __table_.bucket_size(__n);
1992+
}
1993+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_type bucket(const key_type& __k) const { return __table_.bucket(__k); }
19861994

1987-
_LIBCPP_HIDE_FROM_ABI local_iterator begin(size_type __n) { return __table_.begin(__n); }
1988-
_LIBCPP_HIDE_FROM_ABI local_iterator end(size_type __n) { return __table_.end(__n); }
1989-
_LIBCPP_HIDE_FROM_ABI const_local_iterator begin(size_type __n) const { return __table_.cbegin(__n); }
1990-
_LIBCPP_HIDE_FROM_ABI const_local_iterator end(size_type __n) const { return __table_.cend(__n); }
1991-
_LIBCPP_HIDE_FROM_ABI const_local_iterator cbegin(size_type __n) const { return __table_.cbegin(__n); }
1992-
_LIBCPP_HIDE_FROM_ABI const_local_iterator cend(size_type __n) const { return __table_.cend(__n); }
1995+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI local_iterator begin(size_type __n) { return __table_.begin(__n); }
1996+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI local_iterator end(size_type __n) { return __table_.end(__n); }
1997+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_local_iterator begin(size_type __n) const {
1998+
return __table_.cbegin(__n);
1999+
}
2000+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_local_iterator end(size_type __n) const { return __table_.cend(__n); }
2001+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_local_iterator cbegin(size_type __n) const {
2002+
return __table_.cbegin(__n);
2003+
}
2004+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_local_iterator cend(size_type __n) const { return __table_.cend(__n); }
19932005

1994-
_LIBCPP_HIDE_FROM_ABI float load_factor() const _NOEXCEPT { return __table_.load_factor(); }
1995-
_LIBCPP_HIDE_FROM_ABI float max_load_factor() const _NOEXCEPT { return __table_.max_load_factor(); }
2006+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI float load_factor() const _NOEXCEPT { return __table_.load_factor(); }
2007+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI float max_load_factor() const _NOEXCEPT { return __table_.max_load_factor(); }
19962008
_LIBCPP_HIDE_FROM_ABI void max_load_factor(float __mlf) { __table_.max_load_factor(__mlf); }
19972009
_LIBCPP_HIDE_FROM_ABI void rehash(size_type __n) { __table_.__rehash_multi(__n); }
19982010
_LIBCPP_HIDE_FROM_ABI void reserve(size_type __n) { __table_.__reserve_multi(__n); }
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
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+
// Check that functions are marked [[nodiscard]]
10+
11+
#include <unordered_map>
12+
#include <utility>
13+
14+
#include "test_macros.h"
15+
16+
struct TransparentKey {};
17+
18+
struct StoredKey {
19+
friend bool operator==(StoredKey const&, StoredKey const&) { return true; }
20+
friend bool operator==(StoredKey const&, TransparentKey const&) { return true; }
21+
};
22+
23+
struct TransparentKeyHash {
24+
using is_transparent = void;
25+
26+
std::size_t operator()(TransparentKey const&) const { return 0; }
27+
std::size_t operator()(StoredKey const&) const { return 0; }
28+
};
29+
30+
void test() {
31+
std::unordered_multimap<int, int> m;
32+
const std::unordered_multimap<int, int> cm;
33+
34+
m.get_allocator(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
35+
36+
m.empty(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
37+
m.size(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
38+
m.max_size(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
39+
40+
m.begin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
41+
m.end(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
42+
cm.begin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
43+
cm.end(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
44+
cm.cbegin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
45+
cm.cend(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
46+
47+
int key = 0;
48+
49+
#if TEST_STD_VER >= 17
50+
m.extract(0); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
51+
m.extract(m.begin()); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
52+
#endif
53+
54+
m.hash_function(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
55+
m.key_eq(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
56+
57+
m.find(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
58+
cm.find(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
59+
#if TEST_STD_VER >= 20
60+
std::unordered_multimap<StoredKey, int, TransparentKeyHash, std::equal_to<>> tm;
61+
const std::unordered_multimap<StoredKey, int, TransparentKeyHash, std::equal_to<>> ctm;
62+
63+
TransparentKey tkey;
64+
65+
tm.find(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
66+
ctm.find(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
67+
#endif
68+
69+
#if TEST_STD_VER >= 20
70+
m.count(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
71+
cm.count(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
72+
73+
tm.contains(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
74+
ctm.contains(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
75+
#endif
76+
77+
m.equal_range(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
78+
cm.equal_range(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
79+
#if TEST_STD_VER >= 20
80+
tm.equal_range(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
81+
ctm.equal_range(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
82+
#endif
83+
84+
m.bucket_count(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
85+
m.max_bucket_count(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
86+
87+
int size = 0;
88+
89+
m.bucket_size(size); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
90+
m.bucket(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
91+
92+
m.begin(size); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
93+
m.end(size); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
94+
cm.begin(size); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
95+
cm.end(size); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
96+
cm.cbegin(size); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
97+
cm.cend(size); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
98+
99+
m.load_factor(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
100+
m.max_load_factor(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
101+
}

0 commit comments

Comments
 (0)