1 | // RUN: %clang_cc1 -fsyntax-only -verify -Wconsumed -fcxx-exceptions -std=c++11 %s |
2 | |
3 | // TODO: Switch to using macros for the expected warnings. |
4 | |
5 | #define CALLABLE_WHEN(...) __attribute__ ((callable_when(__VA_ARGS__))) |
6 | #define CONSUMABLE(state) __attribute__ ((consumable(state))) |
7 | #define PARAM_TYPESTATE(state) __attribute__ ((param_typestate(state))) |
8 | #define RETURN_TYPESTATE(state) __attribute__ ((return_typestate(state))) |
9 | #define SET_TYPESTATE(state) __attribute__ ((set_typestate(state))) |
10 | #define TEST_TYPESTATE(state) __attribute__ ((test_typestate(state))) |
11 | |
12 | typedef decltype(nullptr) nullptr_t; |
13 | |
14 | template <typename T> |
15 | class CONSUMABLE(unconsumed) ConsumableClass { |
16 | T var; |
17 | |
18 | public: |
19 | ConsumableClass(); |
20 | ConsumableClass(nullptr_t p) RETURN_TYPESTATE(consumed); |
21 | ConsumableClass(T val) RETURN_TYPESTATE(unconsumed); |
22 | ConsumableClass(ConsumableClass<T> &other); |
23 | ConsumableClass(ConsumableClass<T> &&other); |
24 | |
25 | ConsumableClass<T>& operator=(ConsumableClass<T> &other); |
26 | ConsumableClass<T>& operator=(ConsumableClass<T> &&other); |
27 | ConsumableClass<T>& operator=(nullptr_t) SET_TYPESTATE(consumed); |
28 | |
29 | template <typename U> |
30 | ConsumableClass<T>& operator=(ConsumableClass<U> &other); |
31 | |
32 | template <typename U> |
33 | ConsumableClass<T>& operator=(ConsumableClass<U> &&other); |
34 | |
35 | void operator()(int a) SET_TYPESTATE(consumed); |
36 | void operator*() const CALLABLE_WHEN("unconsumed"); |
37 | void unconsumedCall() const CALLABLE_WHEN("unconsumed"); |
38 | void callableWhenUnknown() const CALLABLE_WHEN("unconsumed", "unknown"); |
39 | |
40 | bool isValid() const TEST_TYPESTATE(unconsumed); |
41 | operator bool() const TEST_TYPESTATE(unconsumed); |
42 | bool operator!=(nullptr_t) const TEST_TYPESTATE(unconsumed); |
43 | bool operator==(nullptr_t) const TEST_TYPESTATE(consumed); |
44 | |
45 | void constCall() const; |
46 | void nonconstCall(); |
47 | |
48 | void consume() SET_TYPESTATE(consumed); |
49 | void unconsume() SET_TYPESTATE(unconsumed); |
50 | }; |
51 | |
52 | class CONSUMABLE(unconsumed) DestructorTester { |
53 | public: |
54 | DestructorTester(); |
55 | DestructorTester(int); |
56 | |
57 | void operator*() CALLABLE_WHEN("unconsumed"); |
58 | |
59 | ~DestructorTester() CALLABLE_WHEN("consumed"); |
60 | }; |
61 | |
62 | void baf0(const ConsumableClass<int> var); |
63 | void baf1(const ConsumableClass<int> &var); |
64 | void baf2(const ConsumableClass<int> *var); |
65 | |
66 | void baf3(ConsumableClass<int> var); |
67 | void baf4(ConsumableClass<int> &var); |
68 | void baf5(ConsumableClass<int> *var); |
69 | void baf6(ConsumableClass<int> &&var); |
70 | |
71 | ConsumableClass<int> returnsUnconsumed() { |
72 | return ConsumableClass<int>(); // expected-warning {{return value not in expected state; expected 'unconsumed', observed 'consumed'}} |
73 | } |
74 | |
75 | ConsumableClass<int> returnsConsumed() RETURN_TYPESTATE(consumed); |
76 | ConsumableClass<int> returnsConsumed() { |
77 | return ConsumableClass<int>(); |
78 | } |
79 | |
80 | ConsumableClass<int> returnsUnknown() RETURN_TYPESTATE(unknown); |
81 | |
82 | void testInitialization() { |
83 | ConsumableClass<int> var0; |
84 | ConsumableClass<int> var1 = ConsumableClass<int>(); |
85 | ConsumableClass<int> var2(42); |
86 | ConsumableClass<int> var3(var2); // copy constructor |
87 | ConsumableClass<int> var4(var0); // copy consumed value |
88 | |
89 | *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} |
90 | *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}} |
91 | *var2; |
92 | *var3; |
93 | *var4; // expected-warning {{invalid invocation of method 'operator*' on object 'var4' while it is in the 'consumed' state}} |
94 | |
95 | var0 = ConsumableClass<int>(42); |
96 | *var0; |
97 | |
98 | var0 = var1; |
99 | *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} |
100 | |
101 | if (var0.isValid()) { |
102 | *var0; |
103 | *var1; |
104 | |
105 | } else { |
106 | *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} |
107 | } |
108 | } |
109 | |
110 | void testDestruction() { |
111 | DestructorTester D0(42), D1(42), D2; |
112 | |
113 | *D0; |
114 | *D1; |
115 | *D2; // expected-warning {{invalid invocation of method 'operator*' on object 'D2' while it is in the 'consumed' state}} |
116 | |
117 | D0.~DestructorTester(); // expected-warning {{invalid invocation of method '~DestructorTester' on object 'D0' while it is in the 'unconsumed' state}} |
118 | |
119 | return; // expected-warning {{invalid invocation of method '~DestructorTester' on object 'D0' while it is in the 'unconsumed' state}} \ |
120 | expected-warning {{invalid invocation of method '~DestructorTester' on object 'D1' while it is in the 'unconsumed' state}} |
121 | } |
122 | |
123 | void testTempValue() { |
124 | *ConsumableClass<int>(); // expected-warning {{invalid invocation of method 'operator*' on a temporary object while it is in the 'consumed' state}} |
125 | } |
126 | |
127 | void testSimpleRValueRefs() { |
128 | ConsumableClass<int> var0; |
129 | ConsumableClass<int> var1(42); |
130 | |
131 | *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} |
132 | *var1; |
133 | |
134 | var0 = static_cast<ConsumableClass<int>&&>(var1); |
135 | |
136 | *var0; |
137 | *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}} |
138 | } |
139 | |
140 | void testIfStmt() { |
141 | ConsumableClass<int> var; |
142 | |
143 | if (var.isValid()) { |
144 | *var; |
145 | } else { |
146 | *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}} |
147 | } |
148 | |
149 | if (!var.isValid()) { |
150 | *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}} |
151 | } else { |
152 | *var; |
153 | } |
154 | |
155 | if (var) { |
156 | // Empty |
157 | } else { |
158 | *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}} |
159 | } |
160 | |
161 | if (var != nullptr) { |
162 | // Empty |
163 | } else { |
164 | *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}} |
165 | } |
166 | |
167 | if (var == nullptr) { |
168 | *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}} |
169 | } else { |
170 | // Empty |
171 | } |
172 | } |
173 | |
174 | void testComplexConditionals0() { |
175 | ConsumableClass<int> var0, var1, var2; |
176 | |
177 | if (var0 && var1) { |
178 | *var0; |
179 | *var1; |
180 | |
181 | } else { |
182 | *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} |
183 | *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}} |
184 | } |
185 | |
186 | if (var0 || var1) { |
187 | *var0; |
188 | *var1; |
189 | |
190 | } else { |
191 | *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} |
192 | *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}} |
193 | } |
194 | |
195 | if (var0 && !var1) { |
196 | *var0; |
197 | *var1; |
198 | |
199 | } else { |
200 | *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} |
201 | *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}} |
202 | } |
203 | |
204 | if (var0 || !var1) { |
205 | *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} |
206 | *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}} |
207 | |
208 | } else { |
209 | *var0; |
210 | *var1; |
211 | } |
212 | |
213 | if (!var0 && !var1) { |
214 | *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} |
215 | *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}} |
216 | |
217 | } else { |
218 | *var0; |
219 | *var1; |
220 | } |
221 | |
222 | if (!var0 || !var1) { |
223 | *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} |
224 | *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}} |
225 | |
226 | } else { |
227 | *var0; |
228 | *var1; |
229 | } |
230 | |
231 | if (!(var0 && var1)) { |
232 | *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} |
233 | *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}} |
234 | |
235 | } else { |
236 | *var0; |
237 | *var1; |
238 | } |
239 | |
240 | if (!(var0 || var1)) { |
241 | *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} |
242 | *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}} |
243 | |
244 | } else { |
245 | *var0; |
246 | *var1; |
247 | } |
248 | |
249 | if (var0 && var1 && var2) { |
250 | *var0; |
251 | *var1; |
252 | *var2; |
253 | |
254 | } else { |
255 | *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} |
256 | *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}} |
257 | *var2; // expected-warning {{invalid invocation of method 'operator*' on object 'var2' while it is in the 'consumed' state}} |
258 | } |
259 | |
260 | #if 0 |
261 | // FIXME: Get this test to pass. |
262 | if (var0 || var1 || var2) { |
263 | *var0; |
264 | *var1; |
265 | *var2; |
266 | |
267 | } else { |
268 | *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} |
269 | *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}} |
270 | *var2; // expected-warning {{invalid invocation of method 'operator*' on object 'var2' while it is in the 'consumed' state}} |
271 | } |
272 | #endif |
273 | } |
274 | |
275 | void testComplexConditionals1() { |
276 | ConsumableClass<int> var0, var1, var2; |
277 | |
278 | // Coerce all variables into the unknown state. |
279 | baf4(var0); |
280 | baf4(var1); |
281 | baf4(var2); |
282 | |
283 | if (var0 && var1) { |
284 | *var0; |
285 | *var1; |
286 | |
287 | } else { |
288 | *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'unknown' state}} |
289 | *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'unknown' state}} |
290 | } |
291 | |
292 | if (var0 || var1) { |
293 | *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'unknown' state}} |
294 | *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'unknown' state}} |
295 | |
296 | } else { |
297 | *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} |
298 | *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}} |
299 | } |
300 | |
301 | if (var0 && !var1) { |
302 | *var0; |
303 | *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}} |
304 | |
305 | } else { |
306 | *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'unknown' state}} |
307 | *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'unknown' state}} |
308 | } |
309 | |
310 | if (var0 || !var1) { |
311 | *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'unknown' state}} |
312 | *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'unknown' state}} |
313 | |
314 | } else { |
315 | *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} |
316 | *var1; |
317 | } |
318 | |
319 | if (!var0 && !var1) { |
320 | *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} |
321 | *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}} |
322 | |
323 | } else { |
324 | *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'unknown' state}} |
325 | *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'unknown' state}} |
326 | } |
327 | |
328 | if (!(var0 || var1)) { |
329 | *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} |
330 | *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}} |
331 | |
332 | } else { |
333 | *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'unknown' state}} |
334 | *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'unknown' state}} |
335 | } |
336 | |
337 | if (!var0 || !var1) { |
338 | *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'unknown' state}} |
339 | *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'unknown' state}} |
340 | |
341 | } else { |
342 | *var0; |
343 | *var1; |
344 | } |
345 | |
346 | if (!(var0 && var1)) { |
347 | *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'unknown' state}} |
348 | *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'unknown' state}} |
349 | |
350 | } else { |
351 | *var0; |
352 | *var1; |
353 | } |
354 | |
355 | if (var0 && var1 && var2) { |
356 | *var0; |
357 | *var1; |
358 | *var2; |
359 | |
360 | } else { |
361 | *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'unknown' state}} |
362 | *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'unknown' state}} |
363 | *var2; // expected-warning {{invalid invocation of method 'operator*' on object 'var2' while it is in the 'unknown' state}} |
364 | } |
365 | |
366 | #if 0 |
367 | // FIXME: Get this test to pass. |
368 | if (var0 || var1 || var2) { |
369 | *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'unknown' state}} |
370 | *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'unknown' state}} |
371 | *var2; // expected-warning {{invalid invocation of method 'operator*' on object 'var2' while it is in the 'unknown' state}} |
372 | |
373 | } else { |
374 | *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} |
375 | *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}} |
376 | *var2; // expected-warning {{invalid invocation of method 'operator*' on object 'var2' while it is in the 'consumed' state}} |
377 | } |
378 | #endif |
379 | } |
380 | |
381 | void testStateChangeInBranch() { |
382 | ConsumableClass<int> var; |
383 | |
384 | // Make var enter the 'unknown' state. |
385 | baf4(var); |
386 | |
387 | if (!var) { |
388 | var = ConsumableClass<int>(42); |
389 | } |
390 | |
391 | *var; |
392 | } |
393 | |
394 | void testFunctionParam(ConsumableClass<int> param) { |
395 | |
396 | if (param.isValid()) { |
397 | *param; |
398 | } else { |
399 | *param; |
400 | } |
401 | |
402 | param = nullptr; |
403 | *param; // expected-warning {{invocation of method 'operator*' on object 'param' while it is in the 'consumed' state}} |
404 | } |
405 | |
406 | void testParamReturnTypestateCallee(bool cond, ConsumableClass<int> &Param RETURN_TYPESTATE(unconsumed)) { // expected-warning {{parameter 'Param' not in expected state when the function returns: expected 'unconsumed', observed 'consumed'}} |
407 | |
408 | if (cond) { |
409 | Param.consume(); |
410 | return; // expected-warning {{parameter 'Param' not in expected state when the function returns: expected 'unconsumed', observed 'consumed'}} |
411 | } |
412 | |
413 | Param.consume(); |
414 | } |
415 | |
416 | void testParamReturnTypestateCaller() { |
417 | ConsumableClass<int> var; |
418 | |
419 | testParamReturnTypestateCallee(true, var); |
420 | |
421 | *var; |
422 | } |
423 | |
424 | void testParamTypestateCallee(ConsumableClass<int> Param0 PARAM_TYPESTATE(consumed), |
425 | ConsumableClass<int> &Param1 PARAM_TYPESTATE(consumed)) { |
426 | |
427 | *Param0; // expected-warning {{invalid invocation of method 'operator*' on object 'Param0' while it is in the 'consumed' state}} |
428 | *Param1; // expected-warning {{invalid invocation of method 'operator*' on object 'Param1' while it is in the 'consumed' state}} |
429 | } |
430 | |
431 | void testParamTypestateCaller() { |
432 | ConsumableClass<int> Var0, Var1(42); |
433 | |
434 | testParamTypestateCallee(Var0, Var1); // expected-warning {{argument not in expected state; expected 'consumed', observed 'unconsumed'}} |
435 | } |
436 | |
437 | |
438 | void consumeFunc(ConsumableClass<int> P PARAM_TYPESTATE(unconsumed)); |
439 | struct ParamTest { |
440 | static void consumeFuncStatic(ConsumableClass<int> P PARAM_TYPESTATE(unconsumed)); |
441 | void consumeFuncMeth(ConsumableClass<int> P PARAM_TYPESTATE(unconsumed)); |
442 | void operator<<(ConsumableClass<int> P PARAM_TYPESTATE(unconsumed)); |
443 | }; |
444 | |
445 | void operator>>(ParamTest& pt, ConsumableClass<int> P PARAM_TYPESTATE(unconsumed)); |
446 | |
447 | |
448 | void testFunctionParams() { |
449 | // Make sure we handle the different kinds of functions. |
450 | ConsumableClass<int> P; |
451 | |
452 | consumeFunc(P); // expected-warning {{argument not in expected state; expected 'unconsumed', observed 'consumed'}} |
453 | ParamTest::consumeFuncStatic(P); // expected-warning {{argument not in expected state; expected 'unconsumed', observed 'consumed'}} |
454 | ParamTest pt; |
455 | pt.consumeFuncMeth(P); // expected-warning {{argument not in expected state; expected 'unconsumed', observed 'consumed'}} |
456 | pt << P; // expected-warning {{argument not in expected state; expected 'unconsumed', observed 'consumed'}} |
457 | pt >> P; // expected-warning {{argument not in expected state; expected 'unconsumed', observed 'consumed'}} |
458 | } |
459 | |
460 | void baf3(ConsumableClass<int> var) { |
461 | *var; |
462 | } |
463 | |
464 | void baf4(ConsumableClass<int> &var) { |
465 | *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'unknown' state}} |
466 | } |
467 | |
468 | void baf6(ConsumableClass<int> &&var) { |
469 | *var; |
470 | } |
471 | |
472 | void testCallingConventions() { |
473 | ConsumableClass<int> var(42); |
474 | |
475 | baf0(var); |
476 | *var; |
477 | |
478 | baf1(var); |
479 | *var; |
480 | |
481 | baf2(&var); |
482 | *var; |
483 | |
484 | baf4(var); |
485 | *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'unknown' state}} |
486 | |
487 | var = ConsumableClass<int>(42); |
488 | baf5(&var); |
489 | *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'unknown' state}} |
490 | |
491 | var = ConsumableClass<int>(42); |
492 | baf6(static_cast<ConsumableClass<int>&&>(var)); |
493 | *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}} |
494 | } |
495 | |
496 | void testConstAndNonConstMemberFunctions() { |
497 | ConsumableClass<int> var(42); |
498 | |
499 | var.constCall(); |
500 | *var; |
501 | |
502 | var.nonconstCall(); |
503 | *var; |
504 | } |
505 | |
506 | void testFunctionParam0(ConsumableClass<int> param) { |
507 | *param; |
508 | } |
509 | |
510 | void testFunctionParam1(ConsumableClass<int> ¶m) { |
511 | *param; // expected-warning {{invalid invocation of method 'operator*' on object 'param' while it is in the 'unknown' state}} |
512 | } |
513 | |
514 | void testReturnStates() { |
515 | ConsumableClass<int> var; |
516 | |
517 | var = returnsUnconsumed(); |
518 | *var; |
519 | |
520 | var = returnsConsumed(); |
521 | *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}} |
522 | } |
523 | |
524 | void testCallableWhen() { |
525 | ConsumableClass<int> var(42); |
526 | |
527 | *var; |
528 | |
529 | baf4(var); |
530 | |
531 | var.callableWhenUnknown(); |
532 | } |
533 | |
534 | void testMoveAsignmentish() { |
535 | ConsumableClass<int> var0; |
536 | ConsumableClass<long> var1(42); |
537 | |
538 | *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} |
539 | *var1; |
540 | |
541 | var0 = static_cast<ConsumableClass<long>&&>(var1); |
542 | |
543 | *var0; |
544 | *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}} |
545 | |
546 | var1 = ConsumableClass<long>(42); |
547 | var1 = nullptr; |
548 | *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}} |
549 | } |
550 | |
551 | void testConditionalMerge() { |
552 | ConsumableClass<int> var; |
553 | |
554 | if (var.isValid()) { |
555 | // Empty |
556 | } |
557 | |
558 | *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}} |
559 | |
560 | if (var.isValid()) { |
561 | // Empty |
562 | } else { |
563 | // Empty |
564 | } |
565 | |
566 | *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}} |
567 | } |
568 | |
569 | void testSetTypestate() { |
570 | ConsumableClass<int> var(42); |
571 | |
572 | *var; |
573 | |
574 | var.consume(); |
575 | |
576 | *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}} |
577 | |
578 | var.unconsume(); |
579 | |
580 | *var; |
581 | } |
582 | |
583 | void testConsumes0() { |
584 | ConsumableClass<int> var(nullptr); |
585 | |
586 | *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}} |
587 | } |
588 | |
589 | void testConsumes1() { |
590 | ConsumableClass<int> var(42); |
591 | |
592 | var.unconsumedCall(); |
593 | var(6); |
594 | |
595 | var.unconsumedCall(); // expected-warning {{invalid invocation of method 'unconsumedCall' on object 'var' while it is in the 'consumed' state}} |
596 | } |
597 | |
598 | void testUnreachableBlock() { |
599 | ConsumableClass<int> var(42); |
600 | |
601 | if (var) { |
602 | *var; |
603 | } else { |
604 | *var; |
605 | } |
606 | |
607 | *var; |
608 | } |
609 | |
610 | |
611 | void testForLoop1() { |
612 | ConsumableClass<int> var0, var1(42); |
613 | |
614 | for (int i = 0; i < 10; ++i) { // expected-warning {{state of variable 'var1' must match at the entry and exit of loop}} |
615 | *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} |
616 | |
617 | *var1; |
618 | var1.consume(); |
619 | *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}} |
620 | } |
621 | |
622 | *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} |
623 | } |
624 | |
625 | void testWhileLoop1() { |
626 | int i = 10; |
627 | |
628 | ConsumableClass<int> var0, var1(42); |
629 | |
630 | while (i-- > 0) { // expected-warning {{state of variable 'var1' must match at the entry and exit of loop}} |
631 | *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} |
632 | |
633 | *var1; |
634 | var1.consume(); |
635 | *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}} |
636 | } |
637 | |
638 | *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} |
639 | } |
640 | |
641 | // Tests if state information is correctly discarded for certain shapes of CFGs. |
642 | void testSwitchGOTO(void) { |
643 | int a; |
644 | |
645 | LABEL0: |
646 | switch (a) |
647 | case 0: |
648 | goto LABEL0; |
649 | |
650 | goto LABEL0; |
651 | } |
652 | |
653 | typedef const int*& IntegerPointerReference; |
654 | void testIsRValueRefishAndCanonicalType(IntegerPointerReference a) {} |
655 | |
656 | namespace ContinueICETest { |
657 | |
658 | bool cond1(); |
659 | bool cond2(); |
660 | |
661 | static void foo1() { |
662 | while (cond1()) { |
663 | if (cond2()) |
664 | continue; |
665 | } |
666 | } |
667 | |
668 | static void foo2() { |
669 | while (true) { |
670 | if (false) |
671 | continue; |
672 | } |
673 | } |
674 | |
675 | class runtime_error |
676 | { |
677 | public: |
678 | virtual ~runtime_error(); |
679 | }; |
680 | |
681 | void read(bool sf) { |
682 | while (sf) { |
683 | if(sf) throw runtime_error(); |
684 | } |
685 | } |
686 | |
687 | } // end namespace ContinueICETest |
688 | |
689 | |
690 | namespace StatusUseCaseTests { |
691 | |
692 | class CONSUMABLE(unconsumed) |
693 | __attribute__((consumable_auto_cast_state)) |
694 | __attribute__((consumable_set_state_on_read)) |
695 | Status { |
696 | int code; |
697 | |
698 | public: |
699 | static Status OK; |
700 | |
701 | Status() RETURN_TYPESTATE(consumed); |
702 | Status(int c) RETURN_TYPESTATE(unconsumed); |
703 | |
704 | Status(const Status &other); |
705 | Status(Status &&other); |
706 | |
707 | Status& operator=(const Status &other) CALLABLE_WHEN("unknown", "consumed"); |
708 | Status& operator=(Status &&other) CALLABLE_WHEN("unknown", "consumed"); |
709 | |
710 | bool operator==(const Status &other) const SET_TYPESTATE(consumed); |
711 | |
712 | bool check() const SET_TYPESTATE(consumed); |
713 | void ignore() const SET_TYPESTATE(consumed); |
714 | // Status& markAsChecked() { return *this; } |
715 | |
716 | void clear() CALLABLE_WHEN("unknown", "consumed") SET_TYPESTATE(consumed); |
717 | |
718 | ~Status() CALLABLE_WHEN("unknown", "consumed"); |
719 | |
720 | operator bool() const; // Will not consume the object. |
721 | }; |
722 | |
723 | |
724 | bool cond(); |
725 | Status doSomething(); |
726 | void handleStatus(const Status& s RETURN_TYPESTATE(consumed)); |
727 | void handleStatusRef(Status& s); |
728 | void handleStatusPtr(Status* s); |
729 | void handleStatusUnmarked(const Status& s); |
730 | |
731 | void log(const char* msg); |
732 | void fail() __attribute__((noreturn)); |
733 | void checkStat(const Status& s); |
734 | |
735 | |
736 | void testSimpleTemporaries0() { |
737 | doSomething(); // expected-warning {{invalid invocation of method '~Status' on a temporary object while it is in the 'unconsumed' state}} |
738 | } |
739 | |
740 | void testSimpleTemporaries1() { |
741 | doSomething().ignore(); |
742 | } |
743 | |
744 | void testSimpleTemporaries2() { |
745 | handleStatus(doSomething()); |
746 | } |
747 | |
748 | void testSimpleTemporaries3() { |
749 | Status s = doSomething(); |
750 | } // expected-warning {{invalid invocation of method '~Status' on object 's' while it is in the 'unconsumed' state}} |
751 | |
752 | void testTemporariesWithControlFlow(bool a) { |
753 | bool b = false || doSomething(); // expected-warning {{invalid invocation of method '~Status' on a temporary object while it is in the 'unconsumed' state}} |
754 | } |
755 | |
756 | Status testSimpleTemporariesReturn0() { |
757 | return doSomething(); |
758 | } |
759 | |
760 | Status testSimpleTemporariesReturn1() { |
761 | Status s = doSomething(); |
762 | return s; |
763 | } |
764 | |
765 | void testSimpleTemporaries4() { |
766 | Status s = doSomething(); |
767 | s.check(); |
768 | } |
769 | |
770 | void testSimpleTemporaries5() { |
771 | Status s = doSomething(); |
772 | s.clear(); // expected-warning {{invalid invocation of method 'clear' on object 's' while it is in the 'unconsumed' state}} |
773 | } |
774 | |
775 | void testSimpleTemporaries6() { |
776 | Status s1 = doSomething(); |
777 | handleStatus(s1); |
778 | |
779 | Status s2 = doSomething(); |
780 | handleStatusRef(s2); |
781 | |
782 | Status s3 = doSomething(); |
783 | handleStatusPtr(&s3); |
784 | |
785 | Status s4 = doSomething(); |
786 | handleStatusUnmarked(s4); |
787 | } |
788 | |
789 | void testSimpleTemporaries7() { |
790 | Status s; |
791 | s = doSomething(); |
792 | } // expected-warning {{invalid invocation of method '~Status' on object 's' while it is in the 'unconsumed' state}} |
793 | |
794 | void testTemporariesWithConditionals0() { |
795 | int a; |
796 | |
797 | Status s = doSomething(); |
798 | if (cond()) a = 0; |
799 | else a = 1; |
800 | } // expected-warning {{invalid invocation of method '~Status' on object 's' while it is in the 'unconsumed' state}} |
801 | |
802 | void testTemporariesWithConditionals1() { |
803 | int a; |
804 | |
805 | Status s = doSomething(); |
806 | if (cond()) a = 0; |
807 | else a = 1; |
808 | s.ignore(); |
809 | } |
810 | |
811 | void testTemporariesWithConditionals2() { |
812 | int a; |
813 | |
814 | Status s = doSomething(); |
815 | s.ignore(); |
816 | if (cond()) a = 0; |
817 | else a = 1; |
818 | } |
819 | |
820 | void testTemporariesWithConditionals3() { |
821 | Status s = doSomething(); |
822 | if (cond()) { |
823 | s.check(); |
824 | } |
825 | } |
826 | |
827 | void testTemporariesAndConstructors0() { |
828 | Status s(doSomething()); // Test the copy constructor. |
829 | s.check(); |
830 | } |
831 | |
832 | void testTemporariesAndConstructors1F() { |
833 | Status s1 = doSomething(); // Test the copy constructor. |
834 | Status s2 = s1; |
835 | } // expected-warning {{invalid invocation of method '~Status' on object 's2' while it is in the 'unconsumed' state}} |
836 | |
837 | void testTemporariesAndConstructors1S() { |
838 | Status s1 = doSomething(); // Test the copy constructor. |
839 | Status s2(s1); |
840 | s2.check(); |
841 | } |
842 | |
843 | void testTemporariesAndConstructors2F() { |
844 | // Test the move constructor. |
845 | Status s1 = doSomething(); |
846 | Status s2 = static_cast<Status&&>(s1); |
847 | } // expected-warning {{invalid invocation of method '~Status' on object 's2' while it is in the 'unconsumed' state}} |
848 | |
849 | void testTemporariesAndConstructors2S() { |
850 | // Test the move constructor. |
851 | Status s1 = doSomething(); |
852 | Status s2 = static_cast<Status&&>(s1); |
853 | s2.check(); |
854 | } |
855 | |
856 | void testTemporariesAndOperators0F() { |
857 | // Test the assignment operator. |
858 | Status s1 = doSomething(); |
859 | Status s2; |
860 | s2 = s1; |
861 | } // expected-warning {{invalid invocation of method '~Status' on object 's2' while it is in the 'unconsumed' state}} |
862 | |
863 | void testTemporariesAndOperators0S() { |
864 | // Test the assignment operator. |
865 | Status s1 = doSomething(); |
866 | Status s2; |
867 | s2 = s1; |
868 | s2.check(); |
869 | } |
870 | |
871 | void testTemporariesAndOperators1F() { |
872 | // Test the move assignment operator. |
873 | Status s1 = doSomething(); |
874 | Status s2; |
875 | s2 = static_cast<Status&&>(s1); |
876 | } // expected-warning {{invalid invocation of method '~Status' on object 's2' while it is in the 'unconsumed' state}} |
877 | |
878 | void testTemporariesAndOperators1S() { |
879 | // Test the move assignment operator. |
880 | Status s1 = doSomething(); |
881 | Status s2; |
882 | s2 = static_cast<Status&&>(s1); |
883 | s2.check(); |
884 | } |
885 | |
886 | void testTemporariesAndOperators2() { |
887 | Status s1 = doSomething(); |
888 | Status s2 = doSomething(); |
889 | s1 = s2; // expected-warning {{invalid invocation of method 'operator=' on object 's1' while it is in the 'unconsumed' state}} |
890 | s1.check(); |
891 | s2.check(); |
892 | } |
893 | |
894 | Status testReturnAutocast() { |
895 | Status s = doSomething(); |
896 | s.check(); // consume s |
897 | return s; // should autocast back to unconsumed |
898 | } |
899 | |
900 | |
901 | namespace TestParens { |
902 | |
903 | void test3() { |
904 | checkStat((doSomething())); |
905 | } |
906 | |
907 | void test4() { |
908 | Status s = (doSomething()); |
909 | s.check(); |
910 | } |
911 | |
912 | void test5() { |
913 | (doSomething()).check(); |
914 | } |
915 | |
916 | void test6() { |
917 | if ((doSomething()) == Status::OK) |
918 | return; |
919 | } |
920 | |
921 | } // end namespace TestParens |
922 | |
923 | } // end namespace InitializerAssertionFailTest |
924 | |
925 | |
926 | namespace std { |
927 | void move(); |
928 | template<class T> |
929 | void move(T&&); |
930 | |
931 | namespace __1 { |
932 | void move(); |
933 | template<class T> |
934 | void move(T&&); |
935 | } |
936 | } |
937 | |
938 | namespace PR18260 { |
939 | class X { |
940 | public: |
941 | void move(); |
942 | } x; |
943 | |
944 | void test() { |
945 | x.move(); |
946 | std::move(); |
947 | std::move(x); |
948 | std::__1::move(); |
949 | std::__1::move(x); |
950 | } |
951 | } // end namespace PR18260 |
952 | |
953 | |