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 | |
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 | |
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 | |
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); |
86 | 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(); |
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(); |
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 | |
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> |
150 | auto foo(T) -> decltype(f(), bool()) { // Should not warn. |
151 | return true; |
152 | } |
153 | |
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 { |
168 | virtual void f() {} |
169 | }; |
170 | |
171 | struct D : B { |
172 | void f() override {} |
173 | }; |
174 | |
175 | struct C {}; |
176 | |
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 { |
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 {}; }; |
203 | }; |
204 | |
205 | struct [[clang::warn_unused_result]] P { |
206 | P DoThing() { return {}; }; |
207 | }; |
208 | |
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 {}; }; |
214 | |
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 | |
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 | |