1 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
3 int f() __attribute__((warn_unused_result
));
8 S
g1() __attribute__((warn_unused_result
));
9 S
*g2() __attribute__((warn_unused_result
));
10 S
&g3() __attribute__((warn_unused_result
));
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}}
36 void testSubstmts(int i
) {
39 f(); // expected-warning {{ignoring return value}}
41 f(); // expected-warning {{ignoring return value}}
45 f(); // expected-warning {{ignoring return value}}
47 f(); // expected-warning {{ignoring return value}}
50 f(); // expected-warning {{ignoring return value}}
53 f(); // expected-warning {{ignoring return value}}
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}}
67 int foo() __attribute__((warn_unused_result
));
72 x
.foo(); // expected-warning {{ignoring return value}}
73 x2
->foo(); // expected-warning {{ignoring return value}}
76 namespace warn_unused_CXX11
{
83 struct [[clang::warn_unused_result
]] Status
{
85 Status
& operator=(const Status
& x
);
86 inline void Update(const Status
& new_status
) {
88 *this = new_status
; //no-warning
93 Status
& DoSomethingElse();
94 Status
* DoAnotherThing();
95 Status
** DoYetAnotherThing();
97 Status s
= DoSomething();
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;
107 (void)DoSomethingElse();
108 (void)DoAnotherThing();
109 (void)DoYetAnotherThing();
111 DoSomething(); // expected-warning {{ignoring return value of type 'Status' declared with 'warn_unused_result'}}
117 template <typename T
>
118 class [[clang::warn_unused_result
]] StatusOr
{
120 StatusOr
<int> doit();
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'}}
132 struct [[clang::warn_unused_result
]] Status
;
142 f
.Bar(); // expected-warning {{ignoring return value of type 'Status' declared with 'warn_unused_result'}}
148 // Unevaluated contexts should not trigger unused result warnings.
149 template <typename T
>
150 auto foo(T
) -> decltype(f(), bool()) { // Should not warn.
164 // The typeid expression operand is evaluated only when the expression type is
165 // a glvalue of polymorphic class type.
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.
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.
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 {}; };
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.
241 [[clang::warn_unused_result
]] int f(int);
246 f(b
); // expected-warning {{ignoring return value of function declared with 'warn_unused_result'}}
248 } // namespace PR39837
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
;
262 indirect
indirectf1();
264 af1(); // expected-warning {{ignoring return value of type 'a' declared with 'warn_unused_result'}}
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}}
276 b1f1(); // no warning
277 b2f1(); // no warning
279 __attribute__((warn_unused_result
)) typedef void *c
;
282 cf1(); // expected-warning {{ignoring return value of type 'c' declared with 'warn_unused_result'}}
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) {} };
297 S
<T
> obtain(const T
&) { return {2}; }
300 [[nodiscard
]] S
<T
> obtain2(const T
&) { return {2}; }
303 __attribute__((warn_unused_result
)) S
<T
> obtain3(const T
&) { return {2}; }
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
326 [[nodiscard
]] explicit H(double) {}
327 __attribute__((warn_unused_result
)) H(const char*) {}
330 struct [[nodiscard
]] G
{
332 [[nodiscard
]] explicit G(double) {}
333 [[clang::warn_unused_result
]] G(const char*) {}
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
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
357 } // namespace nodiscard_specialization