Skip to content

Commit aa16e23

Browse files
committed
[libc++][set] Applied [[nodiscard]]
`[[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/map
1 parent a9cc7fe commit aa16e23

File tree

3 files changed

+163
-47
lines changed

3 files changed

+163
-47
lines changed

libcxx/include/set

Lines changed: 49 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -701,24 +701,28 @@ public:
701701

702702
_LIBCPP_HIDE_FROM_ABI ~set() { static_assert(sizeof(std::__diagnose_non_const_comparator<_Key, _Compare>()), ""); }
703703

704-
_LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT { return __tree_.begin(); }
705-
_LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT { return __tree_.begin(); }
706-
_LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT { return __tree_.end(); }
707-
_LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT { return __tree_.end(); }
704+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT { return __tree_.begin(); }
705+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT { return __tree_.begin(); }
706+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT { return __tree_.end(); }
707+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT { return __tree_.end(); }
708708

709-
_LIBCPP_HIDE_FROM_ABI reverse_iterator rbegin() _NOEXCEPT { return reverse_iterator(end()); }
710-
_LIBCPP_HIDE_FROM_ABI const_reverse_iterator rbegin() const _NOEXCEPT { return const_reverse_iterator(end()); }
711-
_LIBCPP_HIDE_FROM_ABI reverse_iterator rend() _NOEXCEPT { return reverse_iterator(begin()); }
712-
_LIBCPP_HIDE_FROM_ABI const_reverse_iterator rend() const _NOEXCEPT { return const_reverse_iterator(begin()); }
709+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI reverse_iterator rbegin() _NOEXCEPT { return reverse_iterator(end()); }
710+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_reverse_iterator rbegin() const _NOEXCEPT {
711+
return const_reverse_iterator(end());
712+
}
713+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI reverse_iterator rend() _NOEXCEPT { return reverse_iterator(begin()); }
714+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_reverse_iterator rend() const _NOEXCEPT {
715+
return const_reverse_iterator(begin());
716+
}
713717

714-
_LIBCPP_HIDE_FROM_ABI const_iterator cbegin() const _NOEXCEPT { return begin(); }
715-
_LIBCPP_HIDE_FROM_ABI const_iterator cend() const _NOEXCEPT { return end(); }
716-
_LIBCPP_HIDE_FROM_ABI const_reverse_iterator crbegin() const _NOEXCEPT { return rbegin(); }
717-
_LIBCPP_HIDE_FROM_ABI const_reverse_iterator crend() const _NOEXCEPT { return rend(); }
718+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator cbegin() const _NOEXCEPT { return begin(); }
719+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator cend() const _NOEXCEPT { return end(); }
720+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_reverse_iterator crbegin() const _NOEXCEPT { return rbegin(); }
721+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_reverse_iterator crend() const _NOEXCEPT { return rend(); }
718722

719723
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT { return __tree_.size() == 0; }
720-
_LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT { return __tree_.size(); }
721-
_LIBCPP_HIDE_FROM_ABI size_type max_size() const _NOEXCEPT { return __tree_.max_size(); }
724+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT { return __tree_.size(); }
725+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_type max_size() const _NOEXCEPT { return __tree_.max_size(); }
722726

723727
// modifiers:
724728
# ifndef _LIBCPP_CXX03_LANG
@@ -777,10 +781,10 @@ public:
777781
"node_type with incompatible allocator passed to set::insert()");
778782
return __tree_.template __node_handle_insert_unique<node_type>(__hint, std::move(__nh));
779783
}
780-
_LIBCPP_HIDE_FROM_ABI node_type extract(key_type const& __key) {
784+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI node_type extract(key_type const& __key) {
781785
return __tree_.template __node_handle_extract<node_type>(__key);
782786
}
783-
_LIBCPP_HIDE_FROM_ABI node_type extract(const_iterator __it) {
787+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI node_type extract(const_iterator __it) {
784788
return __tree_.template __node_handle_extract<node_type>(__it);
785789
}
786790
template <class _Compare2>
@@ -811,90 +815,96 @@ public:
811815

812816
_LIBCPP_HIDE_FROM_ABI void swap(set& __s) _NOEXCEPT_(__is_nothrow_swappable_v<__base>) { __tree_.swap(__s.__tree_); }
813817

814-
_LIBCPP_HIDE_FROM_ABI allocator_type get_allocator() const _NOEXCEPT { return __tree_.__alloc(); }
815-
_LIBCPP_HIDE_FROM_ABI key_compare key_comp() const { return __tree_.value_comp(); }
816-
_LIBCPP_HIDE_FROM_ABI value_compare value_comp() const { return __tree_.value_comp(); }
818+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI allocator_type get_allocator() const _NOEXCEPT { return __tree_.__alloc(); }
819+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI key_compare key_comp() const { return __tree_.value_comp(); }
820+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI value_compare value_comp() const { return __tree_.value_comp(); }
817821

818822
// set operations:
819-
_LIBCPP_HIDE_FROM_ABI iterator find(const key_type& __k) { return __tree_.find(__k); }
820-
_LIBCPP_HIDE_FROM_ABI const_iterator find(const key_type& __k) const { return __tree_.find(__k); }
823+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iterator find(const key_type& __k) { return __tree_.find(__k); }
824+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator find(const key_type& __k) const { return __tree_.find(__k); }
821825
# if _LIBCPP_STD_VER >= 14
822826
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
823-
_LIBCPP_HIDE_FROM_ABI iterator find(const _K2& __k) {
827+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iterator find(const _K2& __k) {
824828
return __tree_.find(__k);
825829
}
826830
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
827-
_LIBCPP_HIDE_FROM_ABI const_iterator find(const _K2& __k) const {
831+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator find(const _K2& __k) const {
828832
return __tree_.find(__k);
829833
}
830834
# endif
831835

832-
_LIBCPP_HIDE_FROM_ABI size_type count(const key_type& __k) const { return __tree_.__count_unique(__k); }
836+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_type count(const key_type& __k) const {
837+
return __tree_.__count_unique(__k);
838+
}
833839
# if _LIBCPP_STD_VER >= 14
834840
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
835-
_LIBCPP_HIDE_FROM_ABI size_type count(const _K2& __k) const {
841+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_type count(const _K2& __k) const {
836842
return __tree_.__count_multi(__k);
837843
}
838844
# endif
839845

840846
# if _LIBCPP_STD_VER >= 20
841-
_LIBCPP_HIDE_FROM_ABI bool contains(const key_type& __k) const { return find(__k) != end(); }
847+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool contains(const key_type& __k) const { return find(__k) != end(); }
842848
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
843-
_LIBCPP_HIDE_FROM_ABI bool contains(const _K2& __k) const {
849+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool contains(const _K2& __k) const {
844850
return find(__k) != end();
845851
}
846852
# endif // _LIBCPP_STD_VER >= 20
847853

848-
_LIBCPP_HIDE_FROM_ABI iterator lower_bound(const key_type& __k) { return __tree_.__lower_bound_unique(__k); }
854+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iterator lower_bound(const key_type& __k) {
855+
return __tree_.__lower_bound_unique(__k);
856+
}
849857

850-
_LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const key_type& __k) const {
858+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const key_type& __k) const {
851859
return __tree_.__lower_bound_unique(__k);
852860
}
853861

854862
// The transparent versions of the lookup functions use the _multi version, since a non-element key is allowed to
855863
// match multiple elements.
856864
# if _LIBCPP_STD_VER >= 14
857865
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
858-
_LIBCPP_HIDE_FROM_ABI iterator lower_bound(const _K2& __k) {
866+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iterator lower_bound(const _K2& __k) {
859867
return __tree_.__lower_bound_multi(__k);
860868
}
861869

862870
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
863-
_LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const _K2& __k) const {
871+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const _K2& __k) const {
864872
return __tree_.__lower_bound_multi(__k);
865873
}
866874
# endif
867875

868-
_LIBCPP_HIDE_FROM_ABI iterator upper_bound(const key_type& __k) { return __tree_.__upper_bound_unique(__k); }
876+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iterator upper_bound(const key_type& __k) {
877+
return __tree_.__upper_bound_unique(__k);
878+
}
869879

870-
_LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const key_type& __k) const {
880+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const key_type& __k) const {
871881
return __tree_.__upper_bound_unique(__k);
872882
}
873883

874884
# if _LIBCPP_STD_VER >= 14
875885
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
876-
_LIBCPP_HIDE_FROM_ABI iterator upper_bound(const _K2& __k) {
886+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iterator upper_bound(const _K2& __k) {
877887
return __tree_.__upper_bound_multi(__k);
878888
}
879889
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
880-
_LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const _K2& __k) const {
890+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const _K2& __k) const {
881891
return __tree_.__upper_bound_multi(__k);
882892
}
883893
# endif
884894

885-
_LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> equal_range(const key_type& __k) {
895+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> equal_range(const key_type& __k) {
886896
return __tree_.__equal_range_unique(__k);
887897
}
888-
_LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> equal_range(const key_type& __k) const {
898+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> equal_range(const key_type& __k) const {
889899
return __tree_.__equal_range_unique(__k);
890900
}
891901
# if _LIBCPP_STD_VER >= 14
892902
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
893-
_LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> equal_range(const _K2& __k) {
903+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> equal_range(const _K2& __k) {
894904
return __tree_.__equal_range_multi(__k);
895905
}
896906
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
897-
_LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> equal_range(const _K2& __k) const {
907+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> equal_range(const _K2& __k) const {
898908
return __tree_.__equal_range_multi(__k);
899909
}
900910
# endif
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
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+
// Check that functions are marked [[nodiscard]]
12+
13+
#include <set>
14+
15+
void test() {
16+
std::multiset<int> multiset;
17+
multiset.empty(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
18+
}

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

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

99
// UNSUPPORTED: c++03
1010

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

1313
#include <set>
1414

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

20-
void multiset_test() {
21-
std::multiset<int> multiset;
22-
multiset.empty(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
105+
s.equal_range(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
106+
cs.equal_range(key); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
107+
#if TEST_STD_VER >= 14
108+
s.equal_range(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
109+
cs.equal_range(tkey); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
110+
#endif
23111
}

0 commit comments

Comments
 (0)