1 | // RUN: %check_clang_tidy %s bugprone-unused-return-value %t -- \ |
2 | // RUN: --config="{CheckOptions: {bugprone-unused-return-value.AllowCastToVoid: true}}" -- -fexceptions |
3 | |
4 | namespace std { |
5 | |
6 | struct future {}; |
7 | |
8 | enum class launch { |
9 | async, |
10 | deferred |
11 | }; |
12 | |
13 | template <typename Function, typename... Args> |
14 | future async(Function &&, Args &&...); |
15 | |
16 | template <typename Function, typename... Args> |
17 | future async(launch, Function &&, Args &&...); |
18 | |
19 | template <typename ForwardIt, typename T> |
20 | ForwardIt remove(ForwardIt, ForwardIt, const T &); |
21 | |
22 | template <typename ForwardIt, typename UnaryPredicate> |
23 | ForwardIt remove_if(ForwardIt, ForwardIt, UnaryPredicate); |
24 | |
25 | template <typename ForwardIt> |
26 | ForwardIt unique(ForwardIt, ForwardIt); |
27 | |
28 | template <typename T> |
29 | struct default_delete; |
30 | |
31 | template <typename T, typename Deleter = std::default_delete<T>> |
32 | struct unique_ptr { |
33 | unique_ptr(); |
34 | unique_ptr(unique_ptr const&); |
35 | unique_ptr(unique_ptr &&); |
36 | unique_ptr& operator=(unique_ptr const&); |
37 | unique_ptr& operator=(unique_ptr &&); |
38 | T *release() noexcept; |
39 | }; |
40 | |
41 | template <typename T> |
42 | struct char_traits; |
43 | |
44 | template <typename T> |
45 | struct allocator; |
46 | |
47 | template <typename CharT, |
48 | typename Traits = char_traits<CharT>, |
49 | typename Allocator = allocator<CharT>> |
50 | struct basic_string { |
51 | bool empty() const; |
52 | }; |
53 | |
54 | typedef basic_string<char> string; |
55 | |
56 | template <typename T, typename Allocator = std::allocator<T>> |
57 | struct vector { |
58 | bool empty() const noexcept; |
59 | }; |
60 | |
61 | class error_code { |
62 | }; |
63 | |
64 | // the check should be able to match std lib calls even if the functions are |
65 | // declared inside inline namespaces |
66 | inline namespace v1 { |
67 | |
68 | template <typename T> |
69 | T *launder(T *); |
70 | |
71 | } // namespace v1 |
72 | } // namespace std |
73 | |
74 | struct Foo { |
75 | void f(); |
76 | }; |
77 | |
78 | int increment(int i) { |
79 | return i + 1; |
80 | } |
81 | |
82 | void useFuture(const std::future &fut); |
83 | |
84 | std::error_code errorFunc() { |
85 | return std::error_code(); |
86 | } |
87 | |
88 | void warning() { |
89 | std::async(increment, 42); |
90 | // CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should not be disregarded; neglecting it may lead to errors |
91 | // CHECK-MESSAGES: [[@LINE-2]]:3: note: cast the expression to void to silence this warning |
92 | |
93 | std::async(std::launch::async, increment, 42); |
94 | // CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should not be disregarded; neglecting it may lead to errors |
95 | // CHECK-MESSAGES: [[@LINE-2]]:3: note: cast the expression to void to silence this warning |
96 | |
97 | Foo F; |
98 | std::launder(&F); |
99 | // CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should not be disregarded; neglecting it may lead to errors |
100 | // CHECK-MESSAGES: [[@LINE-2]]:3: note: cast the expression to void to silence this warning |
101 | |
102 | std::remove(nullptr, nullptr, 1); |
103 | // CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should not be disregarded; neglecting it may lead to errors |
104 | // CHECK-MESSAGES: [[@LINE-2]]:3: note: cast the expression to void to silence this warning |
105 | |
106 | std::remove_if(nullptr, nullptr, nullptr); |
107 | // CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should not be disregarded; neglecting it may lead to errors |
108 | // CHECK-MESSAGES: [[@LINE-2]]:3: note: cast the expression to void to silence this warning |
109 | |
110 | std::unique(nullptr, nullptr); |
111 | // CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should not be disregarded; neglecting it may lead to errors |
112 | // CHECK-MESSAGES: [[@LINE-2]]:3: note: cast the expression to void to silence this warning |
113 | |
114 | std::unique_ptr<Foo> UPtr; |
115 | UPtr.release(); |
116 | // CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should not be disregarded; neglecting it may lead to errors |
117 | // CHECK-MESSAGES: [[@LINE-2]]:3: note: cast the expression to void to silence this warning |
118 | |
119 | std::string Str; |
120 | Str.empty(); |
121 | // CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should not be disregarded; neglecting it may lead to errors |
122 | // CHECK-MESSAGES: [[@LINE-2]]:3: note: cast the expression to void to silence this warning |
123 | |
124 | (int)Str.empty(); |
125 | // CHECK-MESSAGES: [[@LINE-1]]:8: warning: the value returned by this function should not be disregarded; neglecting it may lead to errors |
126 | // CHECK-MESSAGES: [[@LINE-2]]:8: note: cast the expression to void to silence this warning |
127 | |
128 | std::vector<Foo> Vec; |
129 | Vec.empty(); |
130 | // CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should not be disregarded; neglecting it may lead to errors |
131 | // CHECK-MESSAGES: [[@LINE-2]]:3: note: cast the expression to void to silence this warning |
132 | |
133 | // test discarding return values inside different kinds of statements |
134 | |
135 | auto Lambda = [] { std::remove(nullptr, nullptr, 1); }; |
136 | // CHECK-MESSAGES: [[@LINE-1]]:22: warning: the value returned by this function should not be disregarded; neglecting it may lead to errors |
137 | // CHECK-MESSAGES: [[@LINE-2]]:22: note: cast the expression to void to silence this warning |
138 | |
139 | if (true) |
140 | std::remove(nullptr, nullptr, 1); |
141 | // CHECK-MESSAGES: [[@LINE-1]]:5: warning: the value returned by this function should not be disregarded; neglecting it may lead to errors |
142 | // CHECK-MESSAGES: [[@LINE-2]]:5: note: cast the expression to void to silence this warning |
143 | else if (true) |
144 | std::remove(nullptr, nullptr, 1); |
145 | // CHECK-MESSAGES: [[@LINE-1]]:5: warning: the value returned by this function should not be disregarded; neglecting it may lead to errors |
146 | // CHECK-MESSAGES: [[@LINE-2]]:5: note: cast the expression to void to silence this warning |
147 | else |
148 | std::remove(nullptr, nullptr, 1); |
149 | // CHECK-MESSAGES: [[@LINE-1]]:5: warning: the value returned by this function should not be disregarded; neglecting it may lead to errors |
150 | // CHECK-MESSAGES: [[@LINE-2]]:5: note: cast the expression to void to silence this warning |
151 | |
152 | while (true) |
153 | std::remove(nullptr, nullptr, 1); |
154 | // CHECK-MESSAGES: [[@LINE-1]]:5: warning: the value returned by this function should not be disregarded; neglecting it may lead to errors |
155 | // CHECK-MESSAGES: [[@LINE-2]]:5: note: cast the expression to void to silence this warning |
156 | |
157 | do |
158 | std::remove(nullptr, nullptr, 1); |
159 | // CHECK-MESSAGES: [[@LINE-1]]:5: warning: the value returned by this function should not be disregarded; neglecting it may lead to errors |
160 | // CHECK-MESSAGES: [[@LINE-2]]:5: note: cast the expression to void to silence this warning |
161 | while (true); |
162 | |
163 | for (;;) |
164 | std::remove(nullptr, nullptr, 1); |
165 | // CHECK-MESSAGES: [[@LINE-1]]:5: warning: the value returned by this function should not be disregarded; neglecting it may lead to errors |
166 | // CHECK-MESSAGES: [[@LINE-2]]:5: note: cast the expression to void to silence this warning |
167 | |
168 | for (std::remove(nullptr, nullptr, 1);;) |
169 | // CHECK-MESSAGES: [[@LINE-1]]:8: warning: the value returned by this function should not be disregarded; neglecting it may lead to errors |
170 | // CHECK-MESSAGES: [[@LINE-2]]:8: note: cast the expression to void to silence this warning |
171 | ; |
172 | |
173 | for (;; std::remove(nullptr, nullptr, 1)) |
174 | // CHECK-MESSAGES: [[@LINE-1]]:11: warning: the value returned by this function should not be disregarded; neglecting it may lead to errors |
175 | // CHECK-MESSAGES: [[@LINE-2]]:11: note: cast the expression to void to silence this warning |
176 | ; |
177 | |
178 | for (auto C : "foo" ) |
179 | std::remove(nullptr, nullptr, 1); |
180 | // CHECK-MESSAGES: [[@LINE-1]]:5: warning: the value returned by this function should not be disregarded; neglecting it may lead to errors |
181 | // CHECK-MESSAGES: [[@LINE-2]]:5: note: cast the expression to void to silence this warning |
182 | |
183 | switch (1) { |
184 | case 1: |
185 | std::remove(nullptr, nullptr, 1); |
186 | // CHECK-MESSAGES: [[@LINE-1]]:5: warning: the value returned by this function should not be disregarded; neglecting it may lead to errors |
187 | // CHECK-MESSAGES: [[@LINE-2]]:5: note: cast the expression to void to silence this warning |
188 | break; |
189 | default: |
190 | std::remove(nullptr, nullptr, 1); |
191 | // CHECK-MESSAGES: [[@LINE-1]]:5: warning: the value returned by this function should not be disregarded; neglecting it may lead to errors |
192 | // CHECK-MESSAGES: [[@LINE-2]]:5: note: cast the expression to void to silence this warning |
193 | break; |
194 | } |
195 | |
196 | try { |
197 | std::remove(nullptr, nullptr, 1); |
198 | // CHECK-MESSAGES: [[@LINE-1]]:5: warning: the value returned by this function should not be disregarded; neglecting it may lead to errors |
199 | // CHECK-MESSAGES: [[@LINE-2]]:5: note: cast the expression to void to silence this warning |
200 | } catch (...) { |
201 | std::remove(nullptr, nullptr, 1); |
202 | // CHECK-MESSAGES: [[@LINE-1]]:5: warning: the value returned by this function should not be disregarded; neglecting it may lead to errors |
203 | // CHECK-MESSAGES: [[@LINE-2]]:5: note: cast the expression to void to silence this warning |
204 | } |
205 | |
206 | errorFunc(); |
207 | // CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should not be disregarded; neglecting it may lead to errors |
208 | // CHECK-MESSAGES: [[@LINE-2]]:3: note: cast the expression to void to silence this warning |
209 | } |
210 | |
211 | void noWarning() { |
212 | auto AsyncRetval1 = std::async(increment, 42); |
213 | auto AsyncRetval2 = std::async(std::launch::async, increment, 42); |
214 | |
215 | Foo FNoWarning; |
216 | auto LaunderRetval = std::launder(&FNoWarning); |
217 | |
218 | auto RemoveRetval = std::remove(nullptr, nullptr, 1); |
219 | |
220 | auto RemoveIfRetval = std::remove_if(nullptr, nullptr, nullptr); |
221 | |
222 | auto UniqueRetval = std::unique(nullptr, nullptr); |
223 | |
224 | std::unique_ptr<Foo> UPtrNoWarning; |
225 | auto ReleaseRetval = UPtrNoWarning.release(); |
226 | |
227 | std::string StrNoWarning; |
228 | auto StrEmptyRetval = StrNoWarning.empty(); |
229 | |
230 | std::vector<Foo> VecNoWarning; |
231 | auto VecEmptyRetval = VecNoWarning.empty(); |
232 | |
233 | (void) errorFunc(); |
234 | |
235 | // test using the return value in different kinds of expressions |
236 | useFuture(fut: std::async(increment, 42)); |
237 | std::launder(&FNoWarning)->f(); |
238 | delete std::launder(&FNoWarning); |
239 | |
240 | if (std::launder(&FNoWarning)) |
241 | ; |
242 | for (; std::launder(&FNoWarning);) |
243 | ; |
244 | while (std::launder(&FNoWarning)) |
245 | ; |
246 | do |
247 | ; |
248 | while (std::launder(&FNoWarning)); |
249 | switch (std::unique(1, 1)) |
250 | ; |
251 | |
252 | // cast to void should allow ignoring the return value |
253 | (void)std::async(increment, 42); |
254 | |
255 | // test discarding return value of functions that are not configured to be checked |
256 | increment(i: 1); |
257 | |
258 | // test that the check is disabled inside GNU statement expressions |
259 | ({ std::async(increment, 42); }); |
260 | auto StmtExprRetval = ({ std::async(increment, 42); }); |
261 | } |
262 | |
263 | namespace gh84314 { |
264 | |
265 | extern std::unique_ptr<int> alloc(); |
266 | void f1(std::unique_ptr<int> &foo) { |
267 | foo = alloc(); |
268 | } |
269 | |
270 | } // namespace gh84314 |