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