summaryrefslogtreecommitdiff
path: root/test/SemaCXX/warn-consumed-analysis.cpp
diff options
context:
space:
mode:
authorDeLesley Hutchins <delesley@google.com>2013-10-04 21:28:06 +0000
committerDeLesley Hutchins <delesley@google.com>2013-10-04 21:28:06 +0000
commit66540857c08de7f1be9bea48381548d3942cf9d1 (patch)
treef7b37bfb773f09b0a81afe3745ae7702fb012b59 /test/SemaCXX/warn-consumed-analysis.cpp
parent1cd6fab3930d5c058c201895654c6b0bd6ecb8c1 (diff)
downloadclang-66540857c08de7f1be9bea48381548d3942cf9d1.tar.gz
Consumed Analysis: Change callable_when so that it can take a list of states
that a function can be called in. This reduced the total number of annotations needed and makes writing more complicated behaviour less burdensome. Patch by chriswails@gmail.com. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@191983 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/SemaCXX/warn-consumed-analysis.cpp')
-rw-r--r--test/SemaCXX/warn-consumed-analysis.cpp265
1 files changed, 207 insertions, 58 deletions
diff --git a/test/SemaCXX/warn-consumed-analysis.cpp b/test/SemaCXX/warn-consumed-analysis.cpp
index 8d4bff705c..c33e3a197a 100644
--- a/test/SemaCXX/warn-consumed-analysis.cpp
+++ b/test/SemaCXX/warn-consumed-analysis.cpp
@@ -1,10 +1,12 @@
// RUN: %clang_cc1 -fsyntax-only -verify -Wconsumed -std=c++11 %s
-#define CALLABLE_WHEN_UNCONSUMED __attribute__ ((callable_when_unconsumed))
-#define CONSUMABLE(state) __attribute__ ((consumable(state)))
-#define CONSUMES __attribute__ ((consumes))
-#define RETURN_TYPESTATE(state) __attribute__ ((return_typestate(state)))
-#define TESTS_UNCONSUMED __attribute__ ((tests_unconsumed))
+// TODO: Switch to using macros for the expected warnings.
+
+#define CALLABLE_WHEN(...) __attribute__ ((callable_when(__VA_ARGS__)))
+#define CONSUMABLE(state) __attribute__ ((consumable(state)))
+#define CONSUMES __attribute__ ((consumes))
+#define RETURN_TYPESTATE(state) __attribute__ ((return_typestate(state)))
+#define TESTS_UNCONSUMED __attribute__ ((tests_unconsumed))
typedef decltype(nullptr) nullptr_t;
@@ -30,8 +32,9 @@ class CONSUMABLE(unconsumed) ConsumableClass {
ConsumableClass<T>& operator=(ConsumableClass<U> &&other);
void operator()(int a) CONSUMES;
- void operator*() const CALLABLE_WHEN_UNCONSUMED;
- void unconsumedCall() const CALLABLE_WHEN_UNCONSUMED;
+ void operator*() const CALLABLE_WHEN("unconsumed");
+ void unconsumedCall() const CALLABLE_WHEN("unconsumed");
+ void callableWhenUnknown() const CALLABLE_WHEN("unconsumed", "unknown");
bool isValid() const TESTS_UNCONSUMED;
operator bool() const TESTS_UNCONSUMED;
@@ -47,7 +50,9 @@ void baf0(const ConsumableClass<int> var);
void baf1(const ConsumableClass<int> &var);
void baf2(const ConsumableClass<int> *var);
-void baf3(ConsumableClass<int> &&var);
+void baf3(ConsumableClass<int> &var);
+void baf4(ConsumableClass<int> *var);
+void baf5(ConsumableClass<int> &&var);
ConsumableClass<int> returnsUnconsumed() {
return ConsumableClass<int>(); // expected-warning {{return value not in expected state; expected 'unconsumed', observed 'consumed'}}
@@ -58,39 +63,41 @@ ConsumableClass<int> returnsConsumed() {
return ConsumableClass<int>();
}
+ConsumableClass<int> returnsUnknown() RETURN_TYPESTATE(unknown);
+
void testInitialization() {
ConsumableClass<int> var0;
ConsumableClass<int> var1 = ConsumableClass<int>();
var0 = ConsumableClass<int>();
- *var0; // expected-warning {{invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}}
- *var1; // expected-warning {{invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}}
+ *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}}
if (var0.isValid()) {
*var0;
*var1;
} else {
- *var0; // expected-warning {{invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}}
+ *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}}
}
}
void testTempValue() {
- *ConsumableClass<int>(); // expected-warning {{invocation of method 'operator*' on a temporary object while it is in the 'consumed' state}}
+ *ConsumableClass<int>(); // expected-warning {{invalid invocation of method 'operator*' on a temporary object while it is in the 'consumed' state}}
}
void testSimpleRValueRefs() {
ConsumableClass<int> var0;
ConsumableClass<int> var1(42);
- *var0; // expected-warning {{invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}}
+ *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}}
*var1;
var0 = static_cast<ConsumableClass<int>&&>(var1);
*var0;
- *var1; // expected-warning {{invocation of method 'operator*' on object 'var1' 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}}
}
void testIfStmt() {
@@ -99,11 +106,11 @@ void testIfStmt() {
if (var.isValid()) {
*var;
} else {
- *var; // expected-warning {{invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
+ *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
}
if (!var.isValid()) {
- *var; // expected-warning {{invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
+ *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
} else {
*var;
}
@@ -111,17 +118,17 @@ void testIfStmt() {
if (var) {
// Empty
} else {
- *var; // expected-warning {{invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
+ *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
}
if (var != nullptr) {
// Empty
} else {
- *var; // expected-warning {{invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
+ *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
}
}
-void testComplexConditionals() {
+void testComplexConditionals0() {
ConsumableClass<int> var0, var1, var2;
if (var0 && var1) {
@@ -129,8 +136,8 @@ void testComplexConditionals() {
*var1;
} else {
- *var0; // expected-warning {{invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}}
- *var1; // expected-warning {{invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}}
+ *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}}
}
if (var0 || var1) {
@@ -138,8 +145,8 @@ void testComplexConditionals() {
*var1;
} else {
- *var0; // expected-warning {{invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}}
- *var1; // expected-warning {{invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}}
+ *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}}
}
if (var0 && !var1) {
@@ -147,13 +154,13 @@ void testComplexConditionals() {
*var1;
} else {
- *var0; // expected-warning {{invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}}
- *var1; // expected-warning {{invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}}
+ *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}}
}
if (var0 || !var1) {
- *var0; // expected-warning {{invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}}
- *var1; // expected-warning {{invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}}
+ *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}}
} else {
*var0;
@@ -161,8 +168,8 @@ void testComplexConditionals() {
}
if (!var0 && !var1) {
- *var0; // expected-warning {{invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}}
- *var1; // expected-warning {{invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}}
+ *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}}
} else {
*var0;
@@ -170,8 +177,8 @@ void testComplexConditionals() {
}
if (!var0 || !var1) {
- *var0; // expected-warning {{invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}}
- *var1; // expected-warning {{invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}}
+ *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}}
} else {
*var0;
@@ -179,8 +186,8 @@ void testComplexConditionals() {
}
if (!(var0 && var1)) {
- *var0; // expected-warning {{invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}}
- *var1; // expected-warning {{invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}}
+ *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}}
} else {
*var0;
@@ -188,8 +195,8 @@ void testComplexConditionals() {
}
if (!(var0 || var1)) {
- *var0; // expected-warning {{invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}}
- *var1; // expected-warning {{invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}}
+ *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}}
} else {
*var0;
@@ -202,9 +209,9 @@ void testComplexConditionals() {
*var2;
} else {
- *var0; // expected-warning {{invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}}
- *var1; // expected-warning {{invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}}
- *var2; // expected-warning {{invocation of method 'operator*' on object 'var2' while it is in the 'consumed' state}}
+ *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; // expected-warning {{invalid invocation of method 'operator*' on object 'var2' while it is in the 'consumed' state}}
}
#if 0
@@ -215,9 +222,115 @@ void testComplexConditionals() {
*var2;
} else {
- *var0; // expected-warning {{invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}}
- *var1; // expected-warning {{invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}}
- *var2; // expected-warning {{invocation of method 'operator*' on object 'var2' while it is in the 'consumed' state}}
+ *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; // expected-warning {{invalid invocation of method 'operator*' on object 'var2' while it is in the 'consumed' state}}
+ }
+#endif
+}
+
+void testComplexConditionals1() {
+ ConsumableClass<int> var0, var1, var2;
+
+ // Coerce all variables into the unknown state.
+ baf3(var0);
+ baf3(var1);
+ baf3(var2);
+
+ if (var0 && var1) {
+ *var0;
+ *var1;
+
+ } else {
+ *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'unknown' state}}
+ *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'unknown' state}}
+ }
+
+ if (var0 || var1) {
+ *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'unknown' state}}
+ *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'unknown' state}}
+
+ } else {
+ *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}}
+ }
+
+ if (var0 && !var1) {
+ *var0;
+ *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}}
+
+ } else {
+ *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'unknown' state}}
+ *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'unknown' state}}
+ }
+
+ if (var0 || !var1) {
+ *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'unknown' state}}
+ *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'unknown' state}}
+
+ } else {
+ *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}}
+ *var1;
+ }
+
+ if (!var0 && !var1) {
+ *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}}
+
+ } else {
+ *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'unknown' state}}
+ *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'unknown' state}}
+ }
+
+ if (!(var0 || var1)) {
+ *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}}
+
+ } else {
+ *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'unknown' state}}
+ *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'unknown' state}}
+ }
+
+ if (!var0 || !var1) {
+ *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'unknown' state}}
+ *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'unknown' state}}
+
+ } else {
+ *var0;
+ *var1;
+ }
+
+ if (!(var0 && var1)) {
+ *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'unknown' state}}
+ *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'unknown' state}}
+
+ } else {
+ *var0;
+ *var1;
+ }
+
+ if (var0 && var1 && var2) {
+ *var0;
+ *var1;
+ *var2;
+
+ } else {
+ *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'unknown' state}}
+ *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'unknown' state}}
+ *var2; // expected-warning {{invalid invocation of method 'operator*' on object 'var2' while it is in the 'unknown' state}}
+ }
+
+#if 0
+ // FIXME: Get this test to pass.
+ if (var0 || var1 || var2) {
+ *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'unknown' state}}
+ *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'unknown' state}}
+ *var2; // expected-warning {{invalid invocation of method 'operator*' on object 'var2' while it is in the 'unknown' state}}
+
+ } else {
+ *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; // expected-warning {{invalid invocation of method 'operator*' on object 'var2' while it is in the 'consumed' state}}
}
#endif
}
@@ -226,7 +339,7 @@ void testStateChangeInBranch() {
ConsumableClass<int> var;
// Make var enter the 'unknown' state.
- baf1(var);
+ baf3(var);
if (!var) {
var = ConsumableClass<int>(42);
@@ -259,8 +372,34 @@ void testCallingConventions() {
baf2(&var);
*var;
- baf3(static_cast<ConsumableClass<int>&&>(var));
- *var; // expected-warning {{invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
+ baf3(var);
+ *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'unknown' state}}
+
+ var = ConsumableClass<int>(42);
+ baf4(&var);
+ *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'unknown' state}}
+
+ var = ConsumableClass<int>(42);
+ baf5(static_cast<ConsumableClass<int>&&>(var));
+ *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
+}
+
+void testConstAndNonConstMemberFunctions() {
+ ConsumableClass<int> var(42);
+
+ var.constCall();
+ *var;
+
+ var.nonconstCall();
+ *var;
+}
+
+void testFunctionParam0(ConsumableClass<int> param) {
+ *param;
+}
+
+void testFunctionParam1(ConsumableClass<int> &param) {
+ *param; // expected-warning {{invalid invocation of method 'operator*' on object 'param' while it is in the 'unknown' state}}
}
void testReturnStates() {
@@ -270,24 +409,34 @@ void testReturnStates() {
*var;
var = returnsConsumed();
- *var; // expected-warning {{invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
+ *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
+}
+
+void testCallableWhen() {
+ ConsumableClass<int> var(42);
+
+ *var;
+
+ baf3(var);
+
+ var.callableWhenUnknown();
}
void testMoveAsignmentish() {
ConsumableClass<int> var0;
ConsumableClass<long> var1(42);
- *var0; // expected-warning {{invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}}
+ *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}}
*var1;
var0 = static_cast<ConsumableClass<long>&&>(var1);
*var0;
- *var1; // expected-warning {{invocation of method 'operator*' on object 'var1' 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}}
var1 = ConsumableClass<long>(42);
var1 = nullptr;
- *var1; // expected-warning {{invocation of method 'operator*' on object 'var1' 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}}
}
void testConditionalMerge() {
@@ -297,7 +446,7 @@ void testConditionalMerge() {
// Empty
}
- *var; // expected-warning {{invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
+ *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
if (var.isValid()) {
// Empty
@@ -305,7 +454,7 @@ void testConditionalMerge() {
// Empty
}
- *var; // expected-warning {{invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
+ *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
}
void testConsumes0() {
@@ -315,13 +464,13 @@ void testConsumes0() {
var.consume();
- *var; // expected-warning {{invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
+ *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
}
void testConsumes1() {
ConsumableClass<int> var(nullptr);
- *var; // expected-warning {{invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
+ *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
}
void testConsumes2() {
@@ -330,10 +479,10 @@ void testConsumes2() {
var.unconsumedCall();
var(6);
- var.unconsumedCall(); // expected-warning {{invocation of method 'unconsumedCall' on object 'var' while it is in the 'consumed' state}}
+ var.unconsumedCall(); // expected-warning {{invalid invocation of method 'unconsumedCall' on object 'var' while it is in the 'consumed' state}}
}
-void testNonsenseState() {
+void testUnreachableBlock() {
ConsumableClass<int> var(42);
if (var) {
@@ -349,10 +498,10 @@ void testSimpleForLoop() {
ConsumableClass<int> var;
for (int i = 0; i < 10; ++i) {
- *var;
+ *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'unknown' state}}
}
- *var;
+ *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'unknown' state}}
}
void testSimpleWhileLoop() {
@@ -361,9 +510,9 @@ void testSimpleWhileLoop() {
ConsumableClass<int> var;
while (i < 10) {
- *var;
+ *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'unknown' state}}
++i;
}
- *var;
+ *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'unknown' state}}
}