[clang] Implement lifetime analysis for lifetime_capture_by(X) (#115921)
[llvm-project.git] / clang / test / SemaCXX / warn-unused-result.cpp
blob682c500dc1d96d6efde3c0bf9e9833639e22bc32
1 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
3 int f() __attribute__((warn_unused_result));
5 struct S {
6 void t() const;
7 };
8 S g1() __attribute__((warn_unused_result));
9 S *g2() __attribute__((warn_unused_result));
10 S &g3() __attribute__((warn_unused_result));
12 void test() {
13 f(); // expected-warning {{ignoring return value}}
14 g1(); // expected-warning {{ignoring return value}}
15 g2(); // expected-warning {{ignoring return value}}
16 g3(); // expected-warning {{ignoring return value}}
18 (void)f();
19 (void)g1();
20 (void)g2();
21 (void)g3();
23 if (f() == 0) return;
25 g1().t();
26 g2()->t();
27 g3().t();
29 int i = f();
30 S s1 = g1();
31 S *s2 = g2();
32 S &s3 = g3();
33 const S &s4 = g1();
36 void testSubstmts(int i) {
37 switch (i) {
38 case 0:
39 f(); // expected-warning {{ignoring return value}}
40 default:
41 f(); // expected-warning {{ignoring return value}}
44 if (i)
45 f(); // expected-warning {{ignoring return value}}
46 else
47 f(); // expected-warning {{ignoring return value}}
49 while (i)
50 f(); // expected-warning {{ignoring return value}}
53 f(); // expected-warning {{ignoring return value}}
54 while (i);
56 for (f(); // expected-warning {{ignoring return value}}
58 f() // expected-warning {{ignoring return value}}
60 f(); // expected-warning {{ignoring return value}}
62 f(), // expected-warning {{ignoring return value}}
63 (void)f();
66 struct X {
67 int foo() __attribute__((warn_unused_result));
70 void bah() {
71 X x, *x2;
72 x.foo(); // expected-warning {{ignoring return value}}
73 x2->foo(); // expected-warning {{ignoring return value}}
76 namespace warn_unused_CXX11 {
77 class Status;
78 class Foo {
79 public:
80 Status doStuff();
83 struct [[clang::warn_unused_result]] Status {
84 bool ok() const;
85 Status& operator=(const Status& x);
86 inline void Update(const Status& new_status) {
87 if (ok()) {
88 *this = new_status; //no-warning
92 Status DoSomething();
93 Status& DoSomethingElse();
94 Status* DoAnotherThing();
95 Status** DoYetAnotherThing();
96 void lazy() {
97 Status s = DoSomething();
98 if (!s.ok()) return;
99 Status &rs = DoSomethingElse();
100 if (!rs.ok()) return;
101 Status *ps = DoAnotherThing();
102 if (!ps->ok()) return;
103 Status **pps = DoYetAnotherThing();
104 if (!(*pps)->ok()) return;
106 (void)DoSomething();
107 (void)DoSomethingElse();
108 (void)DoAnotherThing();
109 (void)DoYetAnotherThing();
111 DoSomething(); // expected-warning {{ignoring return value of type 'Status' declared with 'warn_unused_result'}}
112 DoSomethingElse();
113 DoAnotherThing();
114 DoYetAnotherThing();
117 template <typename T>
118 class [[clang::warn_unused_result]] StatusOr {
120 StatusOr<int> doit();
121 void test() {
122 Foo f;
123 f.doStuff(); // expected-warning {{ignoring return value of type 'Status' declared with 'warn_unused_result'}}
124 doit(); // expected-warning {{ignoring return value of type 'StatusOr<int>' declared with 'warn_unused_result'}}
126 auto func = []() { return Status(); };
127 func(); // expected-warning {{ignoring return value of type 'Status' declared with 'warn_unused_result'}}
131 namespace PR17587 {
132 struct [[clang::warn_unused_result]] Status;
134 struct Foo {
135 Status Bar();
138 struct Status {};
140 void Bar() {
141 Foo f;
142 f.Bar(); // expected-warning {{ignoring return value of type 'Status' declared with 'warn_unused_result'}}
147 namespace PR18571 {
148 // Unevaluated contexts should not trigger unused result warnings.
149 template <typename T>
150 auto foo(T) -> decltype(f(), bool()) { // Should not warn.
151 return true;
154 void g() {
155 foo(1);
159 namespace std {
160 class type_info { };
163 namespace {
164 // The typeid expression operand is evaluated only when the expression type is
165 // a glvalue of polymorphic class type.
167 struct B {
168 virtual void f() {}
171 struct D : B {
172 void f() override {}
175 struct C {};
177 void g() {
178 // The typeid expression operand is evaluated only when the expression type is
179 // a glvalue of polymorphic class type; otherwise the expression operand is not
180 // evaluated and should not trigger a diagnostic.
181 D d;
182 C c;
183 (void)typeid(f(), c); // Should not warn.
184 (void)typeid(f(), d); // expected-warning {{ignoring return value}} expected-warning {{expression with side effects will be evaluated despite being used as an operand to 'typeid'}}
186 // The sizeof expression operand is never evaluated.
187 (void)sizeof(f(), c); // Should not warn.
189 // The noexcept expression operand is never evaluated.
190 (void)noexcept(f(), false); // Should not warn.
194 namespace {
195 // C++ Methods should warn even in their own class.
196 struct [[clang::warn_unused_result]] S {
197 S DoThing() { return {}; };
198 S operator++(int) { return {}; };
199 S operator--(int) { return {}; };
200 // Improperly written prefix.
201 S operator++() { return {}; };
202 S operator--() { return {}; };
205 struct [[clang::warn_unused_result]] P {
206 P DoThing() { return {}; };
209 P operator++(const P &, int) { return {}; };
210 P operator--(const P &, int) { return {}; };
211 // Improperly written prefix.
212 P operator++(const P &) { return {}; };
213 P operator--(const P &) { return {}; };
215 void f() {
216 S s;
217 P p;
218 s.DoThing(); // expected-warning {{ignoring return value of type 'S' declared with 'warn_unused_result'}}
219 p.DoThing(); // expected-warning {{ignoring return value of type 'P' declared with 'warn_unused_result'}}
220 // Only postfix is expected to warn when written correctly.
221 s++; // expected-warning {{ignoring return value of type 'S' declared with 'warn_unused_result'}}
222 s--; // expected-warning {{ignoring return value of type 'S' declared with 'warn_unused_result'}}
223 p++; // expected-warning {{ignoring return value of type 'P' declared with 'warn_unused_result'}}
224 p--; // expected-warning {{ignoring return value of type 'P' declared with 'warn_unused_result'}}
225 // Improperly written prefix operators should still warn.
226 ++s; // expected-warning {{ignoring return value of type 'S' declared with 'warn_unused_result'}}
227 --s; // expected-warning {{ignoring return value of type 'S' declared with 'warn_unused_result'}}
228 ++p; // expected-warning {{ignoring return value of type 'P' declared with 'warn_unused_result'}}
229 --p; // expected-warning {{ignoring return value of type 'P' declared with 'warn_unused_result'}}
231 // Silencing the warning by cast to void still works.
232 (void)s.DoThing();
233 (void)s++;
234 (void)p++;
235 (void)++s;
236 (void)++p;
238 } // namespace
240 namespace PR39837 {
241 [[clang::warn_unused_result]] int f(int);
243 void g() {
244 int a[2];
245 for (int b : a)
246 f(b); // expected-warning {{ignoring return value of function declared with 'warn_unused_result'}}
248 } // namespace PR39837
250 namespace PR45520 {
251 [[nodiscard]] bool (*f)(); // expected-warning {{'nodiscard' attribute only applies to functions, classes, or enumerations}}
252 [[clang::warn_unused_result]] bool (*g)();
253 __attribute__((warn_unused_result)) bool (*h)();
255 void i([[nodiscard]] bool (*fp)()); // expected-warning {{'nodiscard' attribute only applies to functions, classes, or enumerations}}
258 namespace unused_typedef_result {
259 [[clang::warn_unused_result]] typedef void *a;
260 typedef a indirect;
261 a af1();
262 indirect indirectf1();
263 void af2() {
264 af1(); // expected-warning {{ignoring return value of type 'a' declared with 'warn_unused_result'}}
265 void *(*a1)();
266 a1(); // no warning
267 a (*a2)();
268 a2(); // expected-warning {{ignoring return value of type 'a' declared with 'warn_unused_result'}}
269 indirectf1(); // expected-warning {{ignoring return value of type 'a' declared with 'warn_unused_result'}}
271 [[nodiscard]] typedef void *b1; // expected-warning {{'[[nodiscard]]' attribute ignored when applied to a typedef; consider using '__attribute__((warn_unused_result))' or '[[clang::warn_unused_result]]' instead}}
272 [[gnu::warn_unused_result]] typedef void *b2; // expected-warning {{'[[gnu::warn_unused_result]]' attribute ignored when applied to a typedef; consider using '__attribute__((warn_unused_result))' or '[[clang::warn_unused_result]]' instead}}
273 b1 b1f1();
274 b2 b2f1();
275 void bf2() {
276 b1f1(); // no warning
277 b2f1(); // no warning
279 __attribute__((warn_unused_result)) typedef void *c;
280 c cf1();
281 void cf2() {
282 cf1(); // expected-warning {{ignoring return value of type 'c' declared with 'warn_unused_result'}}
283 void *(*c1)();
284 c1();
285 c (*c2)();
286 c2(); // expected-warning {{ignoring return value of type 'c' declared with 'warn_unused_result'}}
290 namespace nodiscard_specialization {
291 // Test to only mark a specialization of class template as nodiscard
292 template<typename T> struct S { S(int) {} };
293 template<> struct [[nodiscard]] S<int> { S(int) {} };
294 template<typename T> struct [[clang::warn_unused_result]] S<const T> { S(int) {} };
296 template<typename T>
297 S<T> obtain(const T&) { return {2}; }
299 template<typename T>
300 [[nodiscard]] S<T> obtain2(const T&) { return {2}; }
302 template<typename T>
303 __attribute__((warn_unused_result)) S<T> obtain3(const T&) { return {2}; }
305 void use() {
306 obtain(1.0); // no warning
307 obtain(1); // expected-warning {{ignoring return value of type 'S<int>' declared with 'nodiscard'}}
308 obtain<const double>(1); // expected-warning {{ignoring return value of type 'S<const double>' declared with 'warn_unused_result'}}
310 S<double>(2); // no warning
311 S<int>(2); // expected-warning {{ignoring temporary of type 'S<int>' declared with 'nodiscard'}}
312 S<const char>(2); // no warning (warn_unused_result does not diagnose constructor temporaries)
314 // function should take precedence over type
315 obtain2(1.0); // expected-warning {{ignoring return value of function declared with 'nodiscard'}}
316 obtain2(1); // expected-warning {{ignoring return value of function declared with 'nodiscard'}}
317 obtain2<const double>(1); // expected-warning {{ignoring return value of function declared with 'nodiscard'}}
318 obtain3(1.0); // expected-warning {{ignoring return value of function declared with 'warn_unused_result'}}
319 obtain3(1); // expected-warning {{ignoring return value of function declared with 'warn_unused_result'}}
320 obtain3<const double>(1); // expected-warning {{ignoring return value of function declared with 'warn_unused_result'}}
323 // Test on constructor nodiscard
324 struct H {
325 explicit H(int) {}
326 [[nodiscard]] explicit H(double) {}
327 __attribute__((warn_unused_result)) H(const char*) {}
330 struct [[nodiscard]] G {
331 explicit G(int) {}
332 [[nodiscard]] explicit G(double) {}
333 [[clang::warn_unused_result]] G(const char*) {}
336 void use2() {
337 H{2}; // no warning
338 H(2.0); // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard'}}
339 H("Hello"); // no warning (warn_unused_result does not diagnose constructor temporaries)
341 // no warning for explicit cast to void
342 (void)H(2);
343 (void)H{2.0};
344 (void)H{"Hello"};
346 // warns for all these invocations
347 // here, constructor/function should take precedence over type
348 G{2}; // expected-warning {{ignoring temporary of type 'G' declared with 'nodiscard'}}
349 G(2.0); // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard'}}
350 G("Hello"); // expected-warning {{ignoring temporary created by a constructor declared with 'warn_unused_result'}}
352 // no warning for explicit cast to void
353 (void)G(2);
354 (void)G{2.0};
355 (void)G{"Hello"};
357 } // namespace nodiscard_specialization