Clang Project

clang_source_code/test/SemaCXX/warn-consumed-analysis.cpp
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
12typedef decltype(nullptr) nullptr_t;
13
14template <typename T>
15class CONSUMABLE(unconsumed) ConsumableClass {
16  T var;
17  
18public:
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
52class CONSUMABLE(unconsumed) DestructorTester {
53public:
54  DestructorTester();
55  DestructorTester(int);
56  
57  void operator*() CALLABLE_WHEN("unconsumed");
58  
59  ~DestructorTester() CALLABLE_WHEN("consumed");
60};
61
62void baf0(const ConsumableClass<int>  var);
63void baf1(const ConsumableClass<int> &var);
64void baf2(const ConsumableClass<int> *var);
65
66void baf3(ConsumableClass<int>   var);
67void baf4(ConsumableClass<int>  &var);
68void baf5(ConsumableClass<int>  *var);
69void baf6(ConsumableClass<int> &&var);
70
71ConsumableClass<int> returnsUnconsumed() {
72  return ConsumableClass<int>(); // expected-warning {{return value not in expected state; expected 'unconsumed', observed 'consumed'}}
73}
74
75ConsumableClass<int> returnsConsumed() RETURN_TYPESTATE(consumed);
76ConsumableClass<int> returnsConsumed() {
77  return ConsumableClass<int>();
78}
79
80ConsumableClass<int> returnsUnknown() RETURN_TYPESTATE(unknown);
81
82void 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
110void 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
123void testTempValue() {
124  *ConsumableClass<int>(); // expected-warning {{invalid invocation of method 'operator*' on a temporary object while it is in the 'consumed' state}}
125}
126
127void 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
140void 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
174void 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
275void 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
381void 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
394void 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
406void 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
416void testParamReturnTypestateCaller() {
417  ConsumableClass<int> var;
418  
419  testParamReturnTypestateCallee(true, var);
420  
421  *var;
422}
423
424void 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
431void 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
438void consumeFunc(ConsumableClass<int> P PARAM_TYPESTATE(unconsumed));
439struct 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
445void operator>>(ParamTest& pt, ConsumableClass<int> P PARAM_TYPESTATE(unconsumed));
446
447
448void 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
460void baf3(ConsumableClass<int> var) {
461  *var;
462}
463
464void 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
468void baf6(ConsumableClass<int> &&var) {
469  *var;
470}
471
472void 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
496void testConstAndNonConstMemberFunctions() {
497  ConsumableClass<int> var(42);
498  
499  var.constCall();
500  *var;
501  
502  var.nonconstCall();
503  *var;
504}
505
506void testFunctionParam0(ConsumableClass<int> param) {
507  *param;
508}
509
510void testFunctionParam1(ConsumableClass<int> &param) {
511  *param; // expected-warning {{invalid invocation of method 'operator*' on object 'param' while it is in the 'unknown' state}}
512}
513
514void 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
524void testCallableWhen() {
525  ConsumableClass<int> var(42);
526  
527  *var;
528  
529  baf4(var);
530  
531  var.callableWhenUnknown();
532}
533
534void 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
551void 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
569void 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
583void 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
589void 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
598void testUnreachableBlock() {
599  ConsumableClass<int> var(42);
600  
601  if (var) {
602    *var;
603  } else {
604    *var;
605  }
606  
607  *var;
608}
609
610
611void 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
625void 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.
642void testSwitchGOTO(void) {
643 int a;
644
645 LABEL0:
646 switch (a)
647 case 0:
648 goto LABEL0;
649
650 goto LABEL0;
651}
652
653typedef const int*& IntegerPointerReference;
654void testIsRValueRefishAndCanonicalType(IntegerPointerReference a) {}
655
656namespace ContinueICETest {
657
658bool cond1();
659bool cond2();
660
661static void foo1() {
662  while (cond1()) {
663    if (cond2())
664      continue;
665  }
666}
667
668static void foo2() {
669  while (true) {
670    if (false)
671      continue;
672  }
673}
674
675class runtime_error
676{
677public:
678  virtual ~runtime_error();
679};
680
681void read(bool sf) {
682    while (sf) {
683        if(sf) throw runtime_error();
684    }
685}
686
687} // end namespace ContinueICETest
688
689
690namespace StatusUseCaseTests {
691
692class CONSUMABLE(unconsumed)
693      __attribute__((consumable_auto_cast_state))
694      __attribute__((consumable_set_state_on_read))
695    Status {
696  int code;
697
698public:
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
724bool   cond();
725Status doSomething();
726void   handleStatus(const Status& s RETURN_TYPESTATE(consumed));
727void   handleStatusRef(Status& s);
728void   handleStatusPtr(Status* s);
729void   handleStatusUnmarked(const Status& s);
730
731void   log(const char* msg);
732void   fail() __attribute__((noreturn));
733void   checkStat(const Status& s);
734
735
736void testSimpleTemporaries0() {
737  doSomething(); // expected-warning {{invalid invocation of method '~Status' on a temporary object while it is in the 'unconsumed' state}}
738}
739
740void testSimpleTemporaries1() {
741  doSomething().ignore();
742}
743
744void testSimpleTemporaries2() {
745  handleStatus(doSomething());
746}
747
748void testSimpleTemporaries3() {
749  Status s = doSomething();
750}  // expected-warning {{invalid invocation of method '~Status' on object 's' while it is in the 'unconsumed' state}}
751
752void 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
756Status testSimpleTemporariesReturn0() {
757  return doSomething();
758}
759
760Status testSimpleTemporariesReturn1() {
761  Status s = doSomething();
762  return s;
763}
764
765void testSimpleTemporaries4() {
766  Status s = doSomething();
767  s.check();
768}
769
770void 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
775void 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
789void 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
794void 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
802void testTemporariesWithConditionals1() {
803  int a;
804  
805  Status s = doSomething();
806  if (cond()) a = 0;
807  else        a = 1;
808  s.ignore();
809}
810
811void testTemporariesWithConditionals2() {
812  int a;
813  
814  Status s = doSomething();
815  s.ignore();
816  if (cond()) a = 0;
817  else        a = 1;
818}
819
820void testTemporariesWithConditionals3() {
821  Status s = doSomething();
822  if (cond()) {
823    s.check();
824  }
825}
826
827void testTemporariesAndConstructors0() {
828  Status s(doSomething());    // Test the copy constructor.
829  s.check();
830}
831
832void 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
837void testTemporariesAndConstructors1S() {
838  Status s1 = doSomething();  // Test the copy constructor.
839  Status s2(s1);
840  s2.check();
841}
842
843void 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
849void testTemporariesAndConstructors2S() {
850  // Test the move constructor.
851  Status s1 = doSomething();
852  Status s2 = static_cast<Status&&>(s1);
853  s2.check();
854}
855
856void 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
863void testTemporariesAndOperators0S() {
864  // Test the assignment operator.
865  Status s1 = doSomething();
866  Status s2;
867  s2 = s1;
868  s2.check();
869}
870
871void 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
878void 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
886void 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
894Status testReturnAutocast() {
895  Status s = doSomething();
896  s.check();  // consume s
897  return s;   // should autocast back to unconsumed
898}
899
900
901namespace TestParens {
902
903void test3() {
904  checkStat((doSomething()));
905}
906
907void test4() {
908  Status s = (doSomething());
909  s.check();
910}
911
912void test5() {
913  (doSomething()).check();
914}
915
916void test6() {
917  if ((doSomething()) == Status::OK)
918    return;
919}
920
921} // end namespace TestParens
922
923} // end namespace InitializerAssertionFailTest
924
925
926namespace 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
938namespace 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