diff options
Diffstat (limited to 'test/SemaCXX/warn-consumed-analysis.cpp')
-rw-r--r-- | test/SemaCXX/warn-consumed-analysis.cpp | 176 |
1 files changed, 147 insertions, 29 deletions
diff --git a/test/SemaCXX/warn-consumed-analysis.cpp b/test/SemaCXX/warn-consumed-analysis.cpp index 2c372c752baf..977b862a92b5 100644 --- a/test/SemaCXX/warn-consumed-analysis.cpp +++ b/test/SemaCXX/warn-consumed-analysis.cpp @@ -51,7 +51,7 @@ public: class CONSUMABLE(unconsumed) DestructorTester { public: - DestructorTester() RETURN_TYPESTATE(unconsumed); + DestructorTester(); DestructorTester(int); void operator*() CALLABLE_WHEN("unconsumed"); @@ -82,11 +82,21 @@ ConsumableClass<int> returnsUnknown() RETURN_TYPESTATE(unknown); void testInitialization() { ConsumableClass<int> var0; ConsumableClass<int> var1 = ConsumableClass<int>(); - - var0 = ConsumableClass<int>(); - + ConsumableClass<int> var2(42); + ConsumableClass<int> var3(var2); // copy constructor + ConsumableClass<int> var4(var0); // copy consumed value + *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}} + *var2; + *var3; + *var4; // expected-warning {{invalid invocation of method 'operator*' on object 'var4' while it is in the 'consumed' state}} + + var0 = ConsumableClass<int>(42); + *var0; + + var0 = var1; + *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} if (var0.isValid()) { *var0; @@ -98,19 +108,16 @@ void testInitialization() { } void testDestruction() { - DestructorTester D0(42), D1(42); + DestructorTester D0(42), D1(42), D2; *D0; *D1; - - DestructorTester D2; - *D2; + *D2; // expected-warning {{invalid invocation of method 'operator*' on object 'D2' while it is in the 'consumed' state}} D0.~DestructorTester(); // expected-warning {{invalid invocation of method '~DestructorTester' on object 'D0' while it is in the 'unconsumed' state}} return; // expected-warning {{invalid invocation of method '~DestructorTester' on object 'D0' while it is in the 'unconsumed' state}} \ - expected-warning {{invalid invocation of method '~DestructorTester' on object 'D1' while it is in the 'unconsumed' state}} \ - expected-warning {{invalid invocation of method '~DestructorTester' on object 'D2' while it is in the 'unconsumed' state}} + expected-warning {{invalid invocation of method '~DestructorTester' on object 'D1' while it is in the 'unconsumed' state}} } void testTempValue() { @@ -427,6 +434,29 @@ void testParamTypestateCaller() { testParamTypestateCallee(Var0, Var1); // expected-warning {{argument not in expected state; expected 'consumed', observed 'unconsumed'}} } + +void consumeFunc(ConsumableClass<int> P PARAM_TYPESTATE(unconsumed)); +struct ParamTest { + static void consumeFuncStatic(ConsumableClass<int> P PARAM_TYPESTATE(unconsumed)); + void consumeFuncMeth(ConsumableClass<int> P PARAM_TYPESTATE(unconsumed)); + void operator<<(ConsumableClass<int> P PARAM_TYPESTATE(unconsumed)); +}; + +void operator>>(ParamTest& pt, ConsumableClass<int> P PARAM_TYPESTATE(unconsumed)); + + +void testFunctionParams() { + // Make sure we handle the different kinds of functions. + ConsumableClass<int> P; + + consumeFunc(P); // expected-warning {{argument not in expected state; expected 'unconsumed', observed 'consumed'}} + ParamTest::consumeFuncStatic(P); // expected-warning {{argument not in expected state; expected 'unconsumed', observed 'consumed'}} + ParamTest pt; + pt.consumeFuncMeth(P); // expected-warning {{argument not in expected state; expected 'unconsumed', observed 'consumed'}} + pt << P; // expected-warning {{argument not in expected state; expected 'unconsumed', observed 'consumed'}} + pt >> P; // expected-warning {{argument not in expected state; expected 'unconsumed', observed 'consumed'}} +} + void baf3(ConsumableClass<int> var) { *var; } @@ -645,12 +675,17 @@ void read(bool sf) { } // end namespace ContinueICETest -namespace InitializerAssertionFailTest { +namespace StatusUseCaseTests { -class CONSUMABLE(unconsumed) Status { +class CONSUMABLE(unconsumed) + __attribute__((consumable_auto_cast_state)) + __attribute__((consumable_set_state_on_read)) + Status { int code; public: + static Status OK; + Status() RETURN_TYPESTATE(consumed); Status(int c) RETURN_TYPESTATE(unconsumed); @@ -660,6 +695,8 @@ public: Status& operator=(const Status &other) CALLABLE_WHEN("unknown", "consumed"); Status& operator=(Status &&other) CALLABLE_WHEN("unknown", "consumed"); + bool operator==(const Status &other) const SET_TYPESTATE(consumed); + bool check() const SET_TYPESTATE(consumed); void ignore() const SET_TYPESTATE(consumed); // Status& markAsChecked() { return *this; } @@ -667,13 +704,22 @@ public: void clear() CALLABLE_WHEN("unknown", "consumed") SET_TYPESTATE(consumed); ~Status() CALLABLE_WHEN("unknown", "consumed"); + + operator bool() const; // Will not consume the object. }; bool cond(); Status doSomething(); void handleStatus(const Status& s RETURN_TYPESTATE(consumed)); -void handleStatusPtr(const Status* s); +void handleStatusRef(Status& s); +void handleStatusPtr(Status* s); +void handleStatusUnmarked(const Status& s); + +void log(const char* msg); +void fail() __attribute__((noreturn)); +void checkStat(const Status& s); + void testSimpleTemporaries0() { doSomething(); // expected-warning {{invalid invocation of method '~Status' on a temporary object while it is in the 'unconsumed' state}} @@ -691,6 +737,19 @@ void testSimpleTemporaries3() { Status s = doSomething(); } // expected-warning {{invalid invocation of method '~Status' on object 's' while it is in the 'unconsumed' state}} +void testTemporariesWithControlFlow(bool a) { + bool b = false || doSomething(); // expected-warning {{invalid invocation of method '~Status' on a temporary object while it is in the 'unconsumed' state}} +} + +Status testSimpleTemporariesReturn0() { + return doSomething(); +} + +Status testSimpleTemporariesReturn1() { + Status s = doSomething(); + return s; +} + void testSimpleTemporaries4() { Status s = doSomething(); s.check(); @@ -702,8 +761,17 @@ void testSimpleTemporaries5() { } void testSimpleTemporaries6() { - Status s = doSomething(); - handleStatus(s); + Status s1 = doSomething(); + handleStatus(s1); + + Status s2 = doSomething(); + handleStatusRef(s2); + + Status s3 = doSomething(); + handleStatusPtr(&s3); + + Status s4 = doSomething(); + handleStatusUnmarked(s4); } void testSimpleTemporaries7() { @@ -745,38 +813,58 @@ void testTemporariesWithConditionals3() { } void testTemporariesAndConstructors0() { - Status s(doSomething()); + Status s(doSomething()); // Test the copy constructor. s.check(); } -void testTemporariesAndConstructors1() { - // Test the copy constructor. - - Status s1 = doSomething(); +void testTemporariesAndConstructors1F() { + Status s1 = doSomething(); // Test the copy constructor. + Status s2 = s1; +} // expected-warning {{invalid invocation of method '~Status' on object 's2' while it is in the 'unconsumed' state}} + +void testTemporariesAndConstructors1S() { + Status s1 = doSomething(); // Test the copy constructor. Status s2(s1); s2.check(); -} // expected-warning {{invalid invocation of method '~Status' on object 's1' while it is in the 'unconsumed' state}} +} -void testTemporariesAndConstructors2() { +void testTemporariesAndConstructors2F() { // Test the move constructor. - Status s1 = doSomething(); - Status s2(static_cast<Status&&>(s1)); + Status s2 = static_cast<Status&&>(s1); +} // expected-warning {{invalid invocation of method '~Status' on object 's2' while it is in the 'unconsumed' state}} + +void testTemporariesAndConstructors2S() { + // Test the move constructor. + Status s1 = doSomething(); + Status s2 = static_cast<Status&&>(s1); s2.check(); } -void testTemporariesAndOperators0() { +void testTemporariesAndOperators0F() { + // Test the assignment operator. + Status s1 = doSomething(); + Status s2; + s2 = s1; +} // expected-warning {{invalid invocation of method '~Status' on object 's2' while it is in the 'unconsumed' state}} + +void testTemporariesAndOperators0S() { // Test the assignment operator. - Status s1 = doSomething(); Status s2; s2 = s1; s2.check(); -} // expected-warning {{invalid invocation of method '~Status' on object 's1' while it is in the 'unconsumed' state}} +} -void testTemporariesAndOperators1() { +void testTemporariesAndOperators1F() { + // Test the move assignment operator. + Status s1 = doSomething(); + Status s2; + s2 = static_cast<Status&&>(s1); +} // expected-warning {{invalid invocation of method '~Status' on object 's2' while it is in the 'unconsumed' state}} + +void testTemporariesAndOperators1S() { // Test the move assignment operator. - Status s1 = doSomething(); Status s2; s2 = static_cast<Status&&>(s1); @@ -791,6 +879,35 @@ void testTemporariesAndOperators2() { s2.check(); } +Status testReturnAutocast() { + Status s = doSomething(); + s.check(); // consume s + return s; // should autocast back to unconsumed +} + + +namespace TestParens { + +void test3() { + checkStat((doSomething())); +} + +void test4() { + Status s = (doSomething()); + s.check(); +} + +void test5() { + (doSomething()).check(); +} + +void test6() { + if ((doSomething()) == Status::OK) + return; +} + +} // end namespace TestParens + } // end namespace InitializerAssertionFailTest @@ -820,3 +937,4 @@ namespace PR18260 { std::__1::move(x); } } // end namespace PR18260 + |