1// RUN: %check_clang_tidy %s bugprone-unused-return-value %t -- \
2// RUN: --config="{CheckOptions: {bugprone-unused-return-value.AllowCastToVoid: true}}" -- -fexceptions
3
4namespace std {
5
6struct future {};
7
8enum class launch {
9 async,
10 deferred
11};
12
13template <typename Function, typename... Args>
14future async(Function &&, Args &&...);
15
16template <typename Function, typename... Args>
17future async(launch, Function &&, Args &&...);
18
19template <typename ForwardIt, typename T>
20ForwardIt remove(ForwardIt, ForwardIt, const T &);
21
22template <typename ForwardIt, typename UnaryPredicate>
23ForwardIt remove_if(ForwardIt, ForwardIt, UnaryPredicate);
24
25template <typename ForwardIt>
26ForwardIt unique(ForwardIt, ForwardIt);
27
28template <typename T>
29struct default_delete;
30
31template <typename T, typename Deleter = std::default_delete<T>>
32struct 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
41template <typename T>
42struct char_traits;
43
44template <typename T>
45struct allocator;
46
47template <typename CharT,
48 typename Traits = char_traits<CharT>,
49 typename Allocator = allocator<CharT>>
50struct basic_string {
51 bool empty() const;
52};
53
54typedef basic_string<char> string;
55
56template <typename T, typename Allocator = std::allocator<T>>
57struct vector {
58 bool empty() const noexcept;
59};
60
61class 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
66inline namespace v1 {
67
68template <typename T>
69T *launder(T *);
70
71} // namespace v1
72} // namespace std
73
74struct Foo {
75 void f();
76};
77
78int increment(int i) {
79 return i + 1;
80}
81
82void useFuture(const std::future &fut);
83
84std::error_code errorFunc() {
85 return std::error_code();
86}
87
88void 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
211void 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
263namespace gh84314 {
264
265extern std::unique_ptr<int> alloc();
266void f1(std::unique_ptr<int> &foo) {
267 foo = alloc();
268}
269
270} // namespace gh84314

source code of clang-tools-extra/test/clang-tidy/checkers/bugprone/unused-return-value.cpp