Skip to content

Commit 4c172aa

Browse files
committed
[libc++][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#apply-nodiscard-where-relevant https://wg21.link/map
1 parent a9cc7fe commit 4c172aa

File tree

4 files changed

+192
-54
lines changed

4 files changed

+192
-54
lines changed

libcxx/include/__type_traits/is_generic_transparent_comparator.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
_LIBCPP_BEGIN_NAMESPACE_STD
1919

20-
// This traits returns true if the given _Comparator is known to accept any two types for compaison. This is separate
20+
// This trait returns true if the given _Comparator is known to accept any two types for comparison. This is separate
2121
// from `__is_transparent_v`, since that only enables overloads of specific functions, but doesn't give any semantic
2222
// guarantees. This trait guarantess that the comparator simply calls the appropriate comparison functions for any two
2323
// types.

libcxx/include/map

Lines changed: 59 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1027,33 +1027,37 @@ public:
10271027

10281028
_LIBCPP_HIDE_FROM_ABI ~map() { static_assert(sizeof(std::__diagnose_non_const_comparator<_Key, _Compare>()), ""); }
10291029

1030-
_LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT { return __tree_.begin(); }
1031-
_LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT { return __tree_.begin(); }
1032-
_LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT { return __tree_.end(); }
1033-
_LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT { return __tree_.end(); }
1030+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT { return __tree_.begin(); }
1031+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT { return __tree_.begin(); }
1032+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT { return __tree_.end(); }
1033+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT { return __tree_.end(); }
10341034

1035-
_LIBCPP_HIDE_FROM_ABI reverse_iterator rbegin() _NOEXCEPT { return reverse_iterator(end()); }
1036-
_LIBCPP_HIDE_FROM_ABI const_reverse_iterator rbegin() const _NOEXCEPT { return const_reverse_iterator(end()); }
1037-
_LIBCPP_HIDE_FROM_ABI reverse_iterator rend() _NOEXCEPT { return reverse_iterator(begin()); }
1038-
_LIBCPP_HIDE_FROM_ABI const_reverse_iterator rend() const _NOEXCEPT { return const_reverse_iterator(begin()); }
1035+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI reverse_iterator rbegin() _NOEXCEPT { return reverse_iterator(end()); }
1036+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_reverse_iterator rbegin() const _NOEXCEPT {
1037+
return const_reverse_iterator(end());
1038+
}
1039+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI reverse_iterator rend() _NOEXCEPT { return reverse_iterator(begin()); }
1040+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_reverse_iterator rend() const _NOEXCEPT {
1041+
return const_reverse_iterator(begin());
1042+
}
10391043

1040-
_LIBCPP_HIDE_FROM_ABI const_iterator cbegin() const _NOEXCEPT { return begin(); }
1041-
_LIBCPP_HIDE_FROM_ABI const_iterator cend() const _NOEXCEPT { return end(); }
1042-
_LIBCPP_HIDE_FROM_ABI const_reverse_iterator crbegin() const _NOEXCEPT { return rbegin(); }
1043-
_LIBCPP_HIDE_FROM_ABI const_reverse_iterator crend() const _NOEXCEPT { return rend(); }
1044+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator cbegin() const _NOEXCEPT { return begin(); }
1045+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator cend() const _NOEXCEPT { return end(); }
1046+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_reverse_iterator crbegin() const _NOEXCEPT { return rbegin(); }
1047+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_reverse_iterator crend() const _NOEXCEPT { return rend(); }
10441048

10451049
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT { return __tree_.size() == 0; }
1046-
_LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT { return __tree_.size(); }
1047-
_LIBCPP_HIDE_FROM_ABI size_type max_size() const _NOEXCEPT { return __tree_.max_size(); }
1050+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT { return __tree_.size(); }
1051+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_type max_size() const _NOEXCEPT { return __tree_.max_size(); }
10481052

1049-
_LIBCPP_HIDE_FROM_ABI mapped_type& operator[](const key_type& __k);
1053+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI mapped_type& operator[](const key_type& __k);
10501054
# ifndef _LIBCPP_CXX03_LANG
1051-
_LIBCPP_HIDE_FROM_ABI mapped_type& operator[](key_type&& __k);
1055+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI mapped_type& operator[](key_type&& __k);
10521056
# endif
10531057

10541058
template <class _Arg,
10551059
__enable_if_t<__is_transparently_comparable_v<_Compare, key_type, __remove_cvref_t<_Arg> >, int> = 0>
1056-
_LIBCPP_HIDE_FROM_ABI mapped_type& at(_Arg&& __arg) {
1060+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI mapped_type& at(_Arg&& __arg) {
10571061
auto [_, __child] = __tree_.__find_equal(__arg);
10581062
if (__child == nullptr)
10591063
std::__throw_out_of_range("map::at: key not found");
@@ -1062,19 +1066,23 @@ public:
10621066

10631067
template <class _Arg,
10641068
__enable_if_t<__is_transparently_comparable_v<_Compare, key_type, __remove_cvref_t<_Arg> >, int> = 0>
1065-
_LIBCPP_HIDE_FROM_ABI const mapped_type& at(_Arg&& __arg) const {
1069+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const mapped_type& at(_Arg&& __arg) const {
10661070
auto [_, __child] = __tree_.__find_equal(__arg);
10671071
if (__child == nullptr)
10681072
std::__throw_out_of_range("map::at: key not found");
10691073
return static_cast<__node_pointer>(__child)->__get_value().second;
10701074
}
10711075

1072-
_LIBCPP_HIDE_FROM_ABI mapped_type& at(const key_type& __k);
1073-
_LIBCPP_HIDE_FROM_ABI const mapped_type& at(const key_type& __k) const;
1076+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI mapped_type& at(const key_type& __k);
1077+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const mapped_type& at(const key_type& __k) const;
10741078

1075-
_LIBCPP_HIDE_FROM_ABI allocator_type get_allocator() const _NOEXCEPT { return allocator_type(__tree_.__alloc()); }
1076-
_LIBCPP_HIDE_FROM_ABI key_compare key_comp() const { return __tree_.value_comp().key_comp(); }
1077-
_LIBCPP_HIDE_FROM_ABI value_compare value_comp() const { return value_compare(__tree_.value_comp().key_comp()); }
1079+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI allocator_type get_allocator() const _NOEXCEPT {
1080+
return allocator_type(__tree_.__alloc());
1081+
}
1082+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI key_compare key_comp() const { return __tree_.value_comp().key_comp(); }
1083+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI value_compare value_comp() const {
1084+
return value_compare(__tree_.value_comp().key_comp());
1085+
}
10781086

10791087
# ifndef _LIBCPP_CXX03_LANG
10801088
template <class... _Args>
@@ -1226,10 +1234,10 @@ public:
12261234
"node_type with incompatible allocator passed to map::insert()");
12271235
return __tree_.template __node_handle_insert_unique<node_type>(__hint.__i_, std::move(__nh));
12281236
}
1229-
_LIBCPP_HIDE_FROM_ABI node_type extract(key_type const& __key) {
1237+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI node_type extract(key_type const& __key) {
12301238
return __tree_.template __node_handle_extract<node_type>(__key);
12311239
}
1232-
_LIBCPP_HIDE_FROM_ABI node_type extract(const_iterator __it) {
1240+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI node_type extract(const_iterator __it) {
12331241
return __tree_.template __node_handle_extract<node_type>(__it.__i_);
12341242
}
12351243
template <class _Compare2>
@@ -1260,44 +1268,48 @@ public:
12601268

12611269
_LIBCPP_HIDE_FROM_ABI void swap(map& __m) _NOEXCEPT_(__is_nothrow_swappable_v<__base>) { __tree_.swap(__m.__tree_); }
12621270

1263-
_LIBCPP_HIDE_FROM_ABI iterator find(const key_type& __k) { return __tree_.find(__k); }
1264-
_LIBCPP_HIDE_FROM_ABI const_iterator find(const key_type& __k) const { return __tree_.find(__k); }
1271+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iterator find(const key_type& __k) { return __tree_.find(__k); }
1272+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator find(const key_type& __k) const { return __tree_.find(__k); }
12651273
# if _LIBCPP_STD_VER >= 14
12661274
template <typename _K2,
12671275
enable_if_t<__is_transparent_v<_Compare, _K2> || __is_transparently_comparable_v<_Compare, key_type, _K2>,
12681276
int> = 0>
1269-
_LIBCPP_HIDE_FROM_ABI iterator find(const _K2& __k) {
1277+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iterator find(const _K2& __k) {
12701278
return __tree_.find(__k);
12711279
}
12721280
template <typename _K2,
12731281
enable_if_t<__is_transparent_v<_Compare, _K2> || __is_transparently_comparable_v<_Compare, key_type, _K2>,
12741282
int> = 0>
1275-
_LIBCPP_HIDE_FROM_ABI const_iterator find(const _K2& __k) const {
1283+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator find(const _K2& __k) const {
12761284
return __tree_.find(__k);
12771285
}
12781286
# endif
12791287

1280-
_LIBCPP_HIDE_FROM_ABI size_type count(const key_type& __k) const { return __tree_.__count_unique(__k); }
1288+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_type count(const key_type& __k) const {
1289+
return __tree_.__count_unique(__k);
1290+
}
12811291
# if _LIBCPP_STD_VER >= 14
12821292
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
1283-
_LIBCPP_HIDE_FROM_ABI size_type count(const _K2& __k) const {
1293+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_type count(const _K2& __k) const {
12841294
return __tree_.__count_multi(__k);
12851295
}
12861296
# endif
12871297

12881298
# if _LIBCPP_STD_VER >= 20
1289-
_LIBCPP_HIDE_FROM_ABI bool contains(const key_type& __k) const { return find(__k) != end(); }
1299+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool contains(const key_type& __k) const { return find(__k) != end(); }
12901300
template <typename _K2,
12911301
enable_if_t<__is_transparent_v<_Compare, _K2> || __is_transparently_comparable_v<_Compare, key_type, _K2>,
12921302
int> = 0>
1293-
_LIBCPP_HIDE_FROM_ABI bool contains(const _K2& __k) const {
1303+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool contains(const _K2& __k) const {
12941304
return find(__k) != end();
12951305
}
12961306
# endif // _LIBCPP_STD_VER >= 20
12971307

1298-
_LIBCPP_HIDE_FROM_ABI iterator lower_bound(const key_type& __k) { return __tree_.__lower_bound_unique(__k); }
1308+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iterator lower_bound(const key_type& __k) {
1309+
return __tree_.__lower_bound_unique(__k);
1310+
}
12991311

1300-
_LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const key_type& __k) const {
1312+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const key_type& __k) const {
13011313
return __tree_.__lower_bound_unique(__k);
13021314
}
13031315

@@ -1307,52 +1319,54 @@ public:
13071319
template <typename _K2,
13081320
enable_if_t<__is_transparent_v<_Compare, _K2> || __is_transparently_comparable_v<_Compare, key_type, _K2>,
13091321
int> = 0>
1310-
_LIBCPP_HIDE_FROM_ABI iterator lower_bound(const _K2& __k) {
1322+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iterator lower_bound(const _K2& __k) {
13111323
return __tree_.__lower_bound_multi(__k);
13121324
}
13131325

13141326
template <typename _K2,
13151327
enable_if_t<__is_transparent_v<_Compare, _K2> || __is_transparently_comparable_v<_Compare, key_type, _K2>,
13161328
int> = 0>
1317-
_LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const _K2& __k) const {
1329+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const _K2& __k) const {
13181330
return __tree_.__lower_bound_multi(__k);
13191331
}
13201332
# endif
13211333

1322-
_LIBCPP_HIDE_FROM_ABI iterator upper_bound(const key_type& __k) { return __tree_.__upper_bound_unique(__k); }
1334+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iterator upper_bound(const key_type& __k) {
1335+
return __tree_.__upper_bound_unique(__k);
1336+
}
13231337

1324-
_LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const key_type& __k) const {
1338+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const key_type& __k) const {
13251339
return __tree_.__upper_bound_unique(__k);
13261340
}
13271341

13281342
# if _LIBCPP_STD_VER >= 14
13291343
template <typename _K2,
13301344
enable_if_t<__is_transparent_v<_Compare, _K2> || __is_transparently_comparable_v<_Compare, key_type, _K2>,
13311345
int> = 0>
1332-
_LIBCPP_HIDE_FROM_ABI iterator upper_bound(const _K2& __k) {
1346+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iterator upper_bound(const _K2& __k) {
13331347
return __tree_.__upper_bound_multi(__k);
13341348
}
13351349
template <typename _K2,
13361350
enable_if_t<__is_transparent_v<_Compare, _K2> || __is_transparently_comparable_v<_Compare, key_type, _K2>,
13371351
int> = 0>
1338-
_LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const _K2& __k) const {
1352+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const _K2& __k) const {
13391353
return __tree_.__upper_bound_multi(__k);
13401354
}
13411355
# endif
13421356

1343-
_LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> equal_range(const key_type& __k) {
1357+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> equal_range(const key_type& __k) {
13441358
return __tree_.__equal_range_unique(__k);
13451359
}
1346-
_LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> equal_range(const key_type& __k) const {
1360+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> equal_range(const key_type& __k) const {
13471361
return __tree_.__equal_range_unique(__k);
13481362
}
13491363
# if _LIBCPP_STD_VER >= 14
13501364
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
1351-
_LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> equal_range(const _K2& __k) {
1365+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> equal_range(const _K2& __k) {
13521366
return __tree_.__equal_range_multi(__k);
13531367
}
13541368
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
1355-
_LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> equal_range(const _K2& __k) const {
1369+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> equal_range(const _K2& __k) const {
13561370
return __tree_.__equal_range_multi(__k);
13571371
}
13581372
# endif

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

Lines changed: 114 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,122 @@
88

99
// UNSUPPORTED: c++03
1010

11-
// check that <map> functions are marked [[nodiscard]]
11+
// Check that functions are marked [[nodiscard]]
1212

1313
#include <map>
14+
#include <utility>
15+
#include <string>
1416

15-
void map_test() {
16-
std::map<int, int> map;
17-
map.empty(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
18-
}
17+
#include "test_macros.h"
18+
19+
template <typename T>
20+
struct TransparentKey {
21+
T t;
22+
23+
constexpr explicit operator T() const { return t; }
24+
};
25+
26+
struct TransparentCompare {
27+
using is_transparent = void; // This makes the comparator transparent
28+
29+
template <typename T>
30+
constexpr bool operator()(const T& t, const TransparentKey<T>& transparent) const {
31+
return t < transparent.t;
32+
}
33+
34+
template <typename T>
35+
constexpr bool operator()(const TransparentKey<T>& transparent, const T& t) const {
36+
return transparent.t < t;
37+
}
38+
39+
template <typename T>
40+
constexpr bool operator()(const T& t1, const T& t2) const {
41+
return t1 < t2;
42+
}
43+
};
44+
45+
void test() {
46+
std::map<int, int, TransparentCompare> m;
47+
const std::map<int, int, TransparentCompare> cm{};
48+
49+
m.begin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
50+
cm.begin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
51+
m.end(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
52+
cm.end(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
53+
54+
m.rbegin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
55+
cm.rbegin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
56+
m.rend(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
57+
cm.rend(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
58+
59+
cm.cbegin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
60+
cm.cend(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
61+
cm.crbegin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
62+
cm.crend(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
63+
64+
m.empty(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
65+
m.size(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
66+
m.max_size(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
67+
68+
int key = 0;
69+
70+
m[key]; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
71+
m[std::move(key)]; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
72+
73+
std::map<std::string, int, std::less<>> strMap;
74+
const std::map<std::string, int, std::less<>> cstrMap{};
75+
76+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
77+
strMap.at("zmt");
78+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
79+
cstrMap.at("hkt");
80+
m.at(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
81+
cm.at(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
82+
83+
m.get_allocator(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
84+
m.key_comp(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
85+
m.value_comp(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
86+
87+
#if TEST_STD_VER >= 17
88+
m.extract(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
89+
m.extract(m.cend()); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
90+
#endif
91+
92+
m.find(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
93+
cm.find(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
94+
#if TEST_STD_VER >= 14
95+
TransparentKey<int> tkey;
96+
97+
m.find(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
98+
cm.find(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
99+
#endif
100+
101+
m.count(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
102+
m.count(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
103+
104+
#if TEST_STD_VER >= 20
105+
m.contains(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
106+
m.contains(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
107+
#endif
108+
109+
m.lower_bound(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
110+
cm.lower_bound(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
111+
#if TEST_STD_VER >= 14
112+
m.lower_bound(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
113+
cm.lower_bound(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
114+
#endif
115+
116+
m.upper_bound(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
117+
cm.upper_bound(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
118+
#if TEST_STD_VER >= 14
119+
m.upper_bound(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
120+
cm.upper_bound(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
121+
#endif
19122

20-
void multimap_test() {
21-
std::multimap<int, int> multimap;
22-
multimap.empty(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
123+
m.equal_range(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
124+
cm.equal_range(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
125+
#if TEST_STD_VER >= 14
126+
m.equal_range(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
127+
cm.equal_range(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
128+
#endif
23129
}

0 commit comments

Comments
 (0)