Skip to content

Commit b6d940d

Browse files
authored
[libc++][multimap] Applied [[nodiscard]] (#171644)
`[[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/multimap
1 parent b9d1432 commit b6d940d

File tree

2 files changed

+162
-39
lines changed

2 files changed

+162
-39
lines changed

libcxx/include/map

Lines changed: 53 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1778,28 +1778,36 @@ public:
17781778
static_assert(sizeof(std::__diagnose_non_const_comparator<_Key, _Compare>()), "");
17791779
}
17801780

1781-
_LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT { return __tree_.begin(); }
1782-
_LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT { return __tree_.begin(); }
1783-
_LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT { return __tree_.end(); }
1784-
_LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT { return __tree_.end(); }
1781+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT { return __tree_.begin(); }
1782+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT { return __tree_.begin(); }
1783+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT { return __tree_.end(); }
1784+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT { return __tree_.end(); }
17851785

1786-
_LIBCPP_HIDE_FROM_ABI reverse_iterator rbegin() _NOEXCEPT { return reverse_iterator(end()); }
1787-
_LIBCPP_HIDE_FROM_ABI const_reverse_iterator rbegin() const _NOEXCEPT { return const_reverse_iterator(end()); }
1788-
_LIBCPP_HIDE_FROM_ABI reverse_iterator rend() _NOEXCEPT { return reverse_iterator(begin()); }
1789-
_LIBCPP_HIDE_FROM_ABI const_reverse_iterator rend() const _NOEXCEPT { return const_reverse_iterator(begin()); }
1786+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI reverse_iterator rbegin() _NOEXCEPT { return reverse_iterator(end()); }
1787+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_reverse_iterator rbegin() const _NOEXCEPT {
1788+
return const_reverse_iterator(end());
1789+
}
1790+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI reverse_iterator rend() _NOEXCEPT { return reverse_iterator(begin()); }
1791+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_reverse_iterator rend() const _NOEXCEPT {
1792+
return const_reverse_iterator(begin());
1793+
}
17901794

1791-
_LIBCPP_HIDE_FROM_ABI const_iterator cbegin() const _NOEXCEPT { return begin(); }
1792-
_LIBCPP_HIDE_FROM_ABI const_iterator cend() const _NOEXCEPT { return end(); }
1793-
_LIBCPP_HIDE_FROM_ABI const_reverse_iterator crbegin() const _NOEXCEPT { return rbegin(); }
1794-
_LIBCPP_HIDE_FROM_ABI const_reverse_iterator crend() const _NOEXCEPT { return rend(); }
1795+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator cbegin() const _NOEXCEPT { return begin(); }
1796+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator cend() const _NOEXCEPT { return end(); }
1797+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_reverse_iterator crbegin() const _NOEXCEPT { return rbegin(); }
1798+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_reverse_iterator crend() const _NOEXCEPT { return rend(); }
17951799

17961800
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT { return __tree_.size() == 0; }
1797-
_LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT { return __tree_.size(); }
1798-
_LIBCPP_HIDE_FROM_ABI size_type max_size() const _NOEXCEPT { return __tree_.max_size(); }
1801+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT { return __tree_.size(); }
1802+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_type max_size() const _NOEXCEPT { return __tree_.max_size(); }
17991803

1800-
_LIBCPP_HIDE_FROM_ABI allocator_type get_allocator() const _NOEXCEPT { return allocator_type(__tree_.__alloc()); }
1801-
_LIBCPP_HIDE_FROM_ABI key_compare key_comp() const { return __tree_.value_comp().key_comp(); }
1802-
_LIBCPP_HIDE_FROM_ABI value_compare value_comp() const { return value_compare(__tree_.value_comp().key_comp()); }
1804+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI allocator_type get_allocator() const _NOEXCEPT {
1805+
return allocator_type(__tree_.__alloc());
1806+
}
1807+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI key_compare key_comp() const { return __tree_.value_comp().key_comp(); }
1808+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI value_compare value_comp() const {
1809+
return value_compare(__tree_.value_comp().key_comp());
1810+
}
18031811

18041812
# ifndef _LIBCPP_CXX03_LANG
18051813

@@ -1869,10 +1877,10 @@ public:
18691877
"node_type with incompatible allocator passed to multimap::insert()");
18701878
return __tree_.template __node_handle_insert_multi<node_type>(__hint.__i_, std::move(__nh));
18711879
}
1872-
_LIBCPP_HIDE_FROM_ABI node_type extract(key_type const& __key) {
1880+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI node_type extract(key_type const& __key) {
18731881
return __tree_.template __node_handle_extract<node_type>(__key);
18741882
}
1875-
_LIBCPP_HIDE_FROM_ABI node_type extract(const_iterator __it) {
1883+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI node_type extract(const_iterator __it) {
18761884
return __tree_.template __node_handle_extract<node_type>(__it.__i_);
18771885
}
18781886
template <class _Compare2>
@@ -1907,83 +1915,89 @@ public:
19071915
__tree_.swap(__m.__tree_);
19081916
}
19091917

1910-
_LIBCPP_HIDE_FROM_ABI iterator find(const key_type& __k) { return __tree_.find(__k); }
1911-
_LIBCPP_HIDE_FROM_ABI const_iterator find(const key_type& __k) const { return __tree_.find(__k); }
1918+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iterator find(const key_type& __k) { return __tree_.find(__k); }
1919+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator find(const key_type& __k) const { return __tree_.find(__k); }
19121920
# if _LIBCPP_STD_VER >= 14
19131921
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
1914-
_LIBCPP_HIDE_FROM_ABI iterator find(const _K2& __k) {
1922+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iterator find(const _K2& __k) {
19151923
return __tree_.find(__k);
19161924
}
19171925
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
1918-
_LIBCPP_HIDE_FROM_ABI const_iterator find(const _K2& __k) const {
1926+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator find(const _K2& __k) const {
19191927
return __tree_.find(__k);
19201928
}
19211929
# endif
19221930

1923-
_LIBCPP_HIDE_FROM_ABI size_type count(const key_type& __k) const { return __tree_.__count_multi(__k); }
1931+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_type count(const key_type& __k) const {
1932+
return __tree_.__count_multi(__k);
1933+
}
19241934
# if _LIBCPP_STD_VER >= 14
19251935
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
1926-
_LIBCPP_HIDE_FROM_ABI size_type count(const _K2& __k) const {
1936+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_type count(const _K2& __k) const {
19271937
return __tree_.__count_multi(__k);
19281938
}
19291939
# endif
19301940

19311941
# if _LIBCPP_STD_VER >= 20
1932-
_LIBCPP_HIDE_FROM_ABI bool contains(const key_type& __k) const { return find(__k) != end(); }
1942+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool contains(const key_type& __k) const { return find(__k) != end(); }
19331943
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
1934-
_LIBCPP_HIDE_FROM_ABI bool contains(const _K2& __k) const {
1944+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool contains(const _K2& __k) const {
19351945
return find(__k) != end();
19361946
}
19371947
# endif // _LIBCPP_STD_VER >= 20
19381948

1939-
_LIBCPP_HIDE_FROM_ABI iterator lower_bound(const key_type& __k) { return __tree_.__lower_bound_multi(__k); }
1949+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iterator lower_bound(const key_type& __k) {
1950+
return __tree_.__lower_bound_multi(__k);
1951+
}
19401952

1941-
_LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const key_type& __k) const {
1953+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const key_type& __k) const {
19421954
return __tree_.__lower_bound_multi(__k);
19431955
}
19441956

19451957
# if _LIBCPP_STD_VER >= 14
19461958
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
1947-
_LIBCPP_HIDE_FROM_ABI iterator lower_bound(const _K2& __k) {
1959+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iterator lower_bound(const _K2& __k) {
19481960
return __tree_.__lower_bound_multi(__k);
19491961
}
19501962

19511963
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
1952-
_LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const _K2& __k) const {
1964+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const _K2& __k) const {
19531965
return __tree_.__lower_bound_multi(__k);
19541966
}
19551967
# endif
19561968

1957-
_LIBCPP_HIDE_FROM_ABI iterator upper_bound(const key_type& __k) { return __tree_.__upper_bound_multi(__k); }
1969+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iterator upper_bound(const key_type& __k) {
1970+
return __tree_.__upper_bound_multi(__k);
1971+
}
19581972

1959-
_LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const key_type& __k) const {
1973+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const key_type& __k) const {
19601974
return __tree_.__upper_bound_multi(__k);
19611975
}
19621976

19631977
# if _LIBCPP_STD_VER >= 14
19641978
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
1965-
_LIBCPP_HIDE_FROM_ABI iterator upper_bound(const _K2& __k) {
1979+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iterator upper_bound(const _K2& __k) {
19661980
return __tree_.__upper_bound_multi(__k);
19671981
}
19681982
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
1969-
_LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const _K2& __k) const {
1983+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const _K2& __k) const {
19701984
return __tree_.__upper_bound_multi(__k);
19711985
}
19721986
# endif
19731987

1974-
_LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> equal_range(const key_type& __k) {
1988+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> equal_range(const key_type& __k) {
19751989
return __tree_.__equal_range_multi(__k);
19761990
}
1977-
_LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> equal_range(const key_type& __k) const {
1991+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> equal_range(const key_type& __k) const {
19781992
return __tree_.__equal_range_multi(__k);
19791993
}
19801994
# if _LIBCPP_STD_VER >= 14
19811995
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
1982-
_LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> equal_range(const _K2& __k) {
1996+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> equal_range(const _K2& __k) {
19831997
return __tree_.__equal_range_multi(__k);
19841998
}
19851999
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
1986-
_LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> equal_range(const _K2& __k) const {
2000+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> equal_range(const _K2& __k) const {
19872001
return __tree_.__equal_range_multi(__k);
19882002
}
19892003
# endif
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
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 <map>
12+
#include <string>
13+
#include <utility>
14+
15+
#include "test_macros.h"
16+
17+
#if TEST_STD_VER >= 14
18+
struct TransparentKey {
19+
explicit operator int() const;
20+
};
21+
22+
struct TransparentCompare {
23+
using is_transparent = void; // This makes the comparator transparent
24+
25+
bool operator()(const int&, const TransparentKey&) const;
26+
27+
bool operator()(const TransparentKey&, const int&) const;
28+
29+
bool operator()(const int&, const int&) const;
30+
};
31+
#endif // TEST_STD_VER >= 14
32+
33+
void test() {
34+
std::multimap<int, int> m;
35+
const std::multimap<int, int> cm;
36+
37+
m.begin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
38+
cm.begin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
39+
m.end(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
40+
cm.end(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
41+
42+
m.rbegin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
43+
cm.rbegin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
44+
m.rend(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
45+
cm.rend(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
46+
47+
cm.cbegin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
48+
cm.cend(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
49+
cm.crbegin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
50+
cm.crend(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
51+
52+
m.empty(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
53+
m.size(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
54+
m.max_size(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
55+
56+
m.get_allocator(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
57+
m.key_comp(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
58+
m.value_comp(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
59+
60+
int key = 0;
61+
62+
#if TEST_STD_VER >= 17
63+
m.extract(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
64+
m.extract(m.cend()); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
65+
#endif
66+
67+
m.find(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
68+
cm.find(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
69+
#if TEST_STD_VER >= 14
70+
std::multimap<int, int, TransparentCompare> tm;
71+
const std::multimap<int, int, TransparentCompare> ctm{};
72+
73+
TransparentKey tkey;
74+
75+
tm.find(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
76+
ctm.find(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
77+
#endif
78+
79+
m.count(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
80+
#if TEST_STD_VER >= 14
81+
tm.count(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
82+
#endif
83+
84+
#if TEST_STD_VER >= 20
85+
m.contains(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
86+
tm.contains(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
87+
#endif
88+
89+
m.lower_bound(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
90+
cm.lower_bound(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
91+
#if TEST_STD_VER >= 14
92+
tm.lower_bound(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
93+
ctm.lower_bound(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
94+
#endif
95+
96+
m.upper_bound(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
97+
cm.upper_bound(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
98+
#if TEST_STD_VER >= 14
99+
tm.upper_bound(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
100+
ctm.upper_bound(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
101+
#endif
102+
103+
m.equal_range(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
104+
cm.equal_range(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
105+
#if TEST_STD_VER >= 14
106+
tm.equal_range(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
107+
ctm.equal_range(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
108+
#endif
109+
}

0 commit comments

Comments
 (0)