xref: /llvm-project/clang-tools-extra/test/clang-tidy/checkers/bugprone/unused-return-value.cpp (revision 912ea6e335ca6174b3433fd960ed8b592794361b)
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 
increment(int i)78 int increment(int i) {
79   return i + 1;
80 }
81 
82 void useFuture(const std::future &fut);
83 
errorFunc()84 std::error_code errorFunc() {
85     return std::error_code();
86 }
87 
warning()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 
noWarning()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(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(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();
f1(std::unique_ptr<int> & foo)266 void f1(std::unique_ptr<int> &foo) {
267     foo = alloc();
268 }
269 
270 } // namespace gh84314