Skip to content

Commit 90199e4

Browse files
committed
[libc++] Applied [[nodiscard]] to some general utilities
`[[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 The following has been annotated in this patch: - [x] `bind_back`, `bind_front`, `bind` - [x] `function`, `mem_fn` - [x] `reference_wrapper`
1 parent d162c91 commit 90199e4

File tree

8 files changed

+252
-58
lines changed

8 files changed

+252
-58
lines changed

libcxx/include/__functional/bind.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -278,14 +278,14 @@ template <class _Rp, class _Fp, class... _BoundArgs>
278278
struct is_bind_expression<__bind_r<_Rp, _Fp, _BoundArgs...> > : public true_type {};
279279

280280
template <class _Fp, class... _BoundArgs>
281-
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bind<_Fp, _BoundArgs...>
281+
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bind<_Fp, _BoundArgs...>
282282
bind(_Fp&& __f, _BoundArgs&&... __bound_args) {
283283
typedef __bind<_Fp, _BoundArgs...> type;
284284
return type(std::forward<_Fp>(__f), std::forward<_BoundArgs>(__bound_args)...);
285285
}
286286

287287
template <class _Rp, class _Fp, class... _BoundArgs>
288-
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bind_r<_Rp, _Fp, _BoundArgs...>
288+
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bind_r<_Rp, _Fp, _BoundArgs...>
289289
bind(_Fp&& __f, _BoundArgs&&... __bound_args) {
290290
typedef __bind_r<_Rp, _Fp, _BoundArgs...> type;
291291
return type(std::forward<_Fp>(__f), std::forward<_BoundArgs>(__bound_args)...);

libcxx/include/__functional/bind_back.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr auto __bind_back(_Fn&& __f, _Args&&... __args) n
6464

6565
# if _LIBCPP_STD_VER >= 23
6666
template <class _Fn, class... _Args>
67-
_LIBCPP_HIDE_FROM_ABI constexpr auto bind_back(_Fn&& __f, _Args&&... __args) {
67+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto bind_back(_Fn&& __f, _Args&&... __args) {
6868
static_assert(is_constructible_v<decay_t<_Fn>, _Fn>, "bind_back requires decay_t<F> to be constructible from F");
6969
static_assert(is_move_constructible_v<decay_t<_Fn>>, "bind_back requires decay_t<F> to be move constructible");
7070
static_assert((is_constructible_v<decay_t<_Args>, _Args> && ...),

libcxx/include/__functional/bind_front.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ struct __bind_front_t : __perfect_forward<__bind_front_op, _Fn, _BoundArgs...> {
4343
template <class _Fn, class... _Args>
4444
requires is_constructible_v<decay_t<_Fn>, _Fn> && is_move_constructible_v<decay_t<_Fn>> &&
4545
(is_constructible_v<decay_t<_Args>, _Args> && ...) && (is_move_constructible_v<decay_t<_Args>> && ...)
46-
_LIBCPP_HIDE_FROM_ABI constexpr auto bind_front(_Fn&& __f, _Args&&... __args) {
46+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto bind_front(_Fn&& __f, _Args&&... __args) {
4747
return __bind_front_t<decay_t<_Fn>, decay_t<_Args>...>(std::forward<_Fn>(__f), std::forward<_Args>(__args)...);
4848
}
4949

libcxx/include/__functional/function.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -672,11 +672,11 @@ class function<_Rp(_ArgTypes...)>
672672

673673
# if _LIBCPP_HAS_RTTI
674674
// function target access:
675-
_LIBCPP_HIDE_FROM_ABI const std::type_info& target_type() const _NOEXCEPT;
675+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const std::type_info& target_type() const _NOEXCEPT;
676676
template <typename _Tp>
677-
_LIBCPP_HIDE_FROM_ABI _Tp* target() _NOEXCEPT;
677+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _Tp* target() _NOEXCEPT;
678678
template <typename _Tp>
679-
_LIBCPP_HIDE_FROM_ABI const _Tp* target() const _NOEXCEPT;
679+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const _Tp* target() const _NOEXCEPT;
680680
# endif // _LIBCPP_HAS_RTTI
681681
};
682682

libcxx/include/__functional/mem_fn.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ class __mem_fn : public __weak_result_type<_Tp> {
4343
};
4444

4545
template <class _Rp, class _Tp>
46-
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __mem_fn<_Rp _Tp::*> mem_fn(_Rp _Tp::*__pm) _NOEXCEPT {
46+
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __mem_fn<_Rp _Tp::*>
47+
mem_fn(_Rp _Tp::* __pm) _NOEXCEPT {
4748
return __mem_fn<_Rp _Tp::*>(__pm);
4849
}
4950

libcxx/include/__functional/operations.h

Lines changed: 63 additions & 42 deletions
Large diffs are not rendered by default.

libcxx/include/__functional/reference_wrapper.h

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,11 @@ class reference_wrapper : public __weak_result_type<_Tp> {
5858

5959
// access
6060
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 operator type&() const _NOEXCEPT { return *__f_; }
61-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 type& get() const _NOEXCEPT { return *__f_; }
61+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 type& get() const _NOEXCEPT { return *__f_; }
6262

6363
// invoke
6464
template <class... _ArgTypes>
65-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __invoke_result_t<type&, _ArgTypes...>
65+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __invoke_result_t<type&, _ArgTypes...>
6666
operator()(_ArgTypes&&... __args) const
6767
#if _LIBCPP_STD_VER >= 17
6868
// Since is_nothrow_invocable requires C++17 LWG3764 is not backported
@@ -128,23 +128,25 @@ reference_wrapper(_Tp&) -> reference_wrapper<_Tp>;
128128
#endif
129129

130130
template <class _Tp>
131-
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference_wrapper<_Tp> ref(_Tp& __t) _NOEXCEPT {
131+
[[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI
132+
_LIBCPP_CONSTEXPR_SINCE_CXX20 reference_wrapper<_Tp> ref(_Tp& __t) _NOEXCEPT {
132133
return reference_wrapper<_Tp>(__t);
133134
}
134135

135136
template <class _Tp>
136-
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference_wrapper<_Tp>
137+
[[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference_wrapper<_Tp>
137138
ref(reference_wrapper<_Tp> __t) _NOEXCEPT {
138139
return __t;
139140
}
140141

141142
template <class _Tp>
142-
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference_wrapper<const _Tp> cref(const _Tp& __t) _NOEXCEPT {
143+
[[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference_wrapper<const _Tp>
144+
cref(const _Tp& __t) _NOEXCEPT {
143145
return reference_wrapper<const _Tp>(__t);
144146
}
145147

146148
template <class _Tp>
147-
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference_wrapper<const _Tp>
149+
[[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference_wrapper<const _Tp>
148150
cref(reference_wrapper<_Tp> __t) _NOEXCEPT {
149151
return __t;
150152
}

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

Lines changed: 172 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9-
// UNSUPPORTED: c++03, c++11, c++14, c++17
9+
// UNSUPPORTED: c++03
1010

1111
// check that <functional> functions are marked [[nodiscard]]
1212

@@ -16,5 +16,175 @@
1616

1717
void test() {
1818
int i = 0;
19-
std::identity()(i); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
19+
20+
// Function wrappers
21+
22+
#if !defined(TEST_HAS_NO_RTTI)
23+
std::function<void(int)> f;
24+
const std::function<void(int)> cf;
25+
26+
f.target_type(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
27+
f.target<void(int)>(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
28+
cf.target<void(int)>(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
29+
#endif
30+
struct ZMT {
31+
void member_function() {};
32+
};
33+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
34+
std::mem_fn(&ZMT::member_function);
35+
36+
// Identity
37+
38+
std::identity{}(i); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
39+
40+
// Partial function application
41+
42+
#if TEST_STD_VER >= 23
43+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
44+
std::bind_back([](int a) { return a; }, 94);
45+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
46+
std::bind_front([](int a) { return a; }, 94);
47+
#endif
48+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
49+
std::bind([](int a) { return a; }, 94);
50+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
51+
std::bind<float>([](int a) { return a; }, 94);
52+
53+
// Reference wrappers
54+
std::reference_wrapper<int> rw{i};
55+
rw.get(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
56+
std::function<int(int)> vf;
57+
auto rwf = std::ref(vf);
58+
rwf(1); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
59+
60+
std::ref(i); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
61+
std::cref(i); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
62+
63+
// Operator function objects
64+
65+
// Arithmetic
66+
67+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
68+
std::plus<int>()(94, 82);
69+
#if TEST_STD_VER >= 14
70+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
71+
std::plus<void>{}(94, 82);
72+
#endif
73+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
74+
std::minus<int>()(94, 82);
75+
#if TEST_STD_VER >= 14
76+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
77+
std::minus<void>{}(94, 82);
78+
#endif
79+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
80+
std::multiplies<int>()(94, 82);
81+
#if TEST_STD_VER >= 14
82+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
83+
std::multiplies<void>{}(94, 82);
84+
#endif
85+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
86+
std::divides<int>()(94, 82);
87+
#if TEST_STD_VER >= 14
88+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
89+
std::divides<void>{}(94, 82);
90+
#endif
91+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
92+
std::modulus<int>()(94, 82);
93+
#if TEST_STD_VER >= 14
94+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
95+
std::modulus<void>{}(94, 82);
96+
#endif
97+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
98+
std::negate<int>()(94);
99+
#if TEST_STD_VER >= 14
100+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
101+
std::negate<void>{}(94);
102+
#endif
103+
104+
// Bitwise operations
105+
106+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
107+
std::bit_and<int>()(94, 82);
108+
#if TEST_STD_VER >= 14
109+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
110+
std::bit_and<void>{}(94, 82);
111+
#endif
112+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
113+
std::bit_not<int>()(94);
114+
#if TEST_STD_VER >= 14
115+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
116+
std::bit_not<void>{}(94);
117+
#endif
118+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
119+
std::bit_or<int>()(94, 82);
120+
#if TEST_STD_VER >= 14
121+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
122+
std::bit_or<void>{}(94, 82);
123+
#endif
124+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
125+
std::bit_xor<int>()(94, 82);
126+
#if TEST_STD_VER >= 14
127+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
128+
std::bit_xor<void>{}(94, 82);
129+
#endif
130+
131+
// Comparisons
132+
133+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
134+
std::equal_to<int>()(94, 82);
135+
#if TEST_STD_VER >= 14
136+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
137+
std::equal_to<void>{}(94, 82);
138+
#endif
139+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
140+
std::not_equal_to<int>()(94, 82);
141+
#if TEST_STD_VER >= 14
142+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
143+
std::not_equal_to<void>{}(94, 82);
144+
#endif
145+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
146+
std::less<int>()(94, 82);
147+
#if TEST_STD_VER >= 14
148+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
149+
std::less<void>{}(94, 82);
150+
#endif
151+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
152+
std::less_equal<int>()(94, 82);
153+
#if TEST_STD_VER >= 14
154+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
155+
std::less_equal<void>{}(94, 82);
156+
#endif
157+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
158+
std::greater_equal<int>()(94, 82);
159+
#if TEST_STD_VER >= 14
160+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
161+
std::greater_equal<void>{}(94, 82);
162+
#endif
163+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
164+
std::greater<int>()(94, 82);
165+
#if TEST_STD_VER >= 14
166+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
167+
std::greater<void>{}(94, 82);
168+
#endif
169+
170+
// Logical operations
171+
172+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
173+
std::logical_and<int>()(94, 82);
174+
#if TEST_STD_VER >= 14
175+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
176+
std::logical_and<void>{}(94, 82);
177+
#endif
178+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
179+
std::logical_not<int>()(94);
180+
#if TEST_STD_VER >= 14
181+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
182+
std::logical_not<void>{}(94);
183+
#endif
184+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
185+
std::logical_or<int>()(94, 82);
186+
#if TEST_STD_VER >= 14
187+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
188+
std::logical_or<void>{}(94, 82);
189+
#endif
20190
}

0 commit comments

Comments
 (0)