1 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
2
3 int f() __attribute__((warn_unused_result));
4
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));
11
test()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}}
17
18 (void)f();
19 (void)g1();
20 (void)g2();
21 (void)g3();
22
23 if (f() == 0) return;
24
25 g1().t();
26 g2()->t();
27 g3().t();
28
29 int i = f();
30 S s1 = g1();
31 S *s2 = g2();
32 S &s3 = g3();
33 const S &s4 = g1();
34 }
35
testSubstmts(int i)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}}
42 }
43
44 if (i)
45 f(); // expected-warning {{ignoring return value}}
46 else
47 f(); // expected-warning {{ignoring return value}}
48
49 while (i)
50 f(); // expected-warning {{ignoring return value}}
51
52 do
53 f(); // expected-warning {{ignoring return value}}
54 while (i);
55
56 for (f(); // expected-warning {{ignoring return value}}
57 ;
58 f() // expected-warning {{ignoring return value}}
59 )
60 f(); // expected-warning {{ignoring return value}}
61
62 f(), // expected-warning {{ignoring return value}}
63 (void)f();
64 }
65
66 struct X {
67 int foo() __attribute__((warn_unused_result));
68 };
69
bah()70 void bah() {
71 X x, *x2;
72 x.foo(); // expected-warning {{ignoring return value}}
73 x2->foo(); // expected-warning {{ignoring return value}}
74 }
75
76 namespace warn_unused_CXX11 {
77 class Status;
78 class Foo {
79 public:
80 Status doStuff();
81 };
82
83 struct [[clang::warn_unused_result]] Status {
84 bool ok() const;
85 Status& operator=(const Status& x);
Updatewarn_unused_CXX11::Status86 inline void Update(const Status& new_status) {
87 if (ok()) {
88 *this = new_status; //no-warning
89 }
90 }
91 };
92 Status DoSomething();
93 Status& DoSomethingElse();
94 Status* DoAnotherThing();
95 Status** DoYetAnotherThing();
lazy()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;
105
106 (void)DoSomething();
107 (void)DoSomethingElse();
108 (void)DoAnotherThing();
109 (void)DoYetAnotherThing();
110
111 DoSomething(); // expected-warning {{ignoring return value}}
112 DoSomethingElse();
113 DoAnotherThing();
114 DoYetAnotherThing();
115 }
116
117 template <typename T>
118 class [[clang::warn_unused_result]] StatusOr {
119 };
120 StatusOr<int> doit();
test()121 void test() {
122 Foo f;
123 f.doStuff(); // expected-warning {{ignoring return value}}
124 doit(); // expected-warning {{ignoring return value}}
125
126 auto func = []() { return Status(); };
127 func(); // expected-warning {{ignoring return value}}
128 }
129 }
130
131 namespace PR17587 {
132 struct [[clang::warn_unused_result]] Status;
133
134 struct Foo {
135 Status Bar();
136 };
137
138 struct Status {};
139
Bar()140 void Bar() {
141 Foo f;
142 f.Bar(); // expected-warning {{ignoring return value}}
143 };
144
145 }
146
147 namespace PR18571 {
148 // Unevaluated contexts should not trigger unused result warnings.
149 template <typename T>
foo(T)150 auto foo(T) -> decltype(f(), bool()) { // Should not warn.
151 return true;
152 }
153
g()154 void g() {
155 foo(1);
156 }
157 }
158
159 namespace std {
160 class type_info { };
161 }
162
163 namespace {
164 // The typeid expression operand is evaluated only when the expression type is
165 // a glvalue of polymorphic class type.
166
167 struct B {
f__anon385a54e00211::B168 virtual void f() {}
169 };
170
171 struct D : B {
f__anon385a54e00211::D172 void f() override {}
173 };
174
175 struct C {};
176
g()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'}}
185
186 // The sizeof expression operand is never evaluated.
187 (void)sizeof(f(), c); // Should not warn.
188
189 // The noexcept expression operand is never evaluated.
190 (void)noexcept(f(), false); // Should not warn.
191 }
192 }
193
194 namespace {
195 // C++ Methods should warn even in their own class.
196 struct [[clang::warn_unused_result]] S {
DoThing__anon385a54e00311::S197 S DoThing() { return {}; };
operator ++__anon385a54e00311::S198 S operator++(int) { return {}; };
operator --__anon385a54e00311::S199 S operator--(int) { return {}; };
200 // Improperly written prefix.
operator ++__anon385a54e00311::S201 S operator++() { return {}; };
operator --__anon385a54e00311::S202 S operator--() { return {}; };
203 };
204
205 struct [[clang::warn_unused_result]] P {
DoThing__anon385a54e00311::P206 P DoThing() { return {}; };
207 };
208
operator ++(const P &,int)209 P operator++(const P &, int) { return {}; };
operator --(const P &,int)210 P operator--(const P &, int) { return {}; };
211 // Improperly written prefix.
operator ++(const P &)212 P operator++(const P &) { return {}; };
operator --(const P &)213 P operator--(const P &) { return {}; };
214
f()215 void f() {
216 S s;
217 P p;
218 s.DoThing(); // expected-warning {{ignoring return value}}
219 p.DoThing(); // expected-warning {{ignoring return value}}
220 // Only postfix is expected to warn when written correctly.
221 s++; // expected-warning {{ignoring return value}}
222 s--; // expected-warning {{ignoring return value}}
223 p++; // expected-warning {{ignoring return value}}
224 p--; // expected-warning {{ignoring return value}}
225 // Improperly written prefix operators should still warn.
226 ++s; // expected-warning {{ignoring return value}}
227 --s; // expected-warning {{ignoring return value}}
228 ++p; // expected-warning {{ignoring return value}}
229 --p; // expected-warning {{ignoring return value}}
230
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;
237 }
238 } // namespace
239
240 namespace PR39837 {
241 [[clang::warn_unused_result]] int f(int);
242
g()243 void g() {
244 int a[2];
245 for (int b : a)
246 f(b); // expected-warning {{ignoring return value}}
247 }
248 } // namespace PR39837
249