2013-08-13 05:20:55 +08:00
|
|
|
// RUN: %clang_cc1 -fsyntax-only -verify -Wconsumed -std=c++11 %s
|
|
|
|
|
2013-10-05 05:28:06 +08:00
|
|
|
// 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))
|
2013-08-13 05:20:55 +08:00
|
|
|
|
|
|
|
typedef decltype(nullptr) nullptr_t;
|
|
|
|
|
|
|
|
template <typename T>
|
2013-09-06 09:28:43 +08:00
|
|
|
class CONSUMABLE(unconsumed) ConsumableClass {
|
2013-08-13 05:20:55 +08:00
|
|
|
T var;
|
|
|
|
|
|
|
|
public:
|
2013-08-30 01:26:57 +08:00
|
|
|
ConsumableClass();
|
2013-09-04 04:11:38 +08:00
|
|
|
ConsumableClass(nullptr_t p) RETURN_TYPESTATE(consumed);
|
|
|
|
ConsumableClass(T val) RETURN_TYPESTATE(unconsumed);
|
2013-09-06 09:28:43 +08:00
|
|
|
ConsumableClass(ConsumableClass<T> &other);
|
|
|
|
ConsumableClass(ConsumableClass<T> &&other);
|
2013-08-13 05:20:55 +08:00
|
|
|
|
2013-08-24 02:40:39 +08:00
|
|
|
ConsumableClass<T>& operator=(ConsumableClass<T> &other);
|
|
|
|
ConsumableClass<T>& operator=(ConsumableClass<T> &&other);
|
2013-08-30 05:17:25 +08:00
|
|
|
ConsumableClass<T>& operator=(nullptr_t) CONSUMES;
|
2013-08-13 05:20:55 +08:00
|
|
|
|
|
|
|
template <typename U>
|
2013-08-24 02:40:39 +08:00
|
|
|
ConsumableClass<T>& operator=(ConsumableClass<U> &other);
|
2013-08-13 05:20:55 +08:00
|
|
|
|
|
|
|
template <typename U>
|
2013-08-24 02:40:39 +08:00
|
|
|
ConsumableClass<T>& operator=(ConsumableClass<U> &&other);
|
2013-08-13 05:20:55 +08:00
|
|
|
|
2013-08-23 04:44:47 +08:00
|
|
|
void operator()(int a) CONSUMES;
|
2013-10-05 05:28:06 +08:00
|
|
|
void operator*() const CALLABLE_WHEN("unconsumed");
|
|
|
|
void unconsumedCall() const CALLABLE_WHEN("unconsumed");
|
|
|
|
void callableWhenUnknown() const CALLABLE_WHEN("unconsumed", "unknown");
|
2013-08-13 05:20:55 +08:00
|
|
|
|
2013-08-30 01:26:57 +08:00
|
|
|
bool isValid() const TESTS_UNCONSUMED;
|
2013-08-13 05:20:55 +08:00
|
|
|
operator bool() const TESTS_UNCONSUMED;
|
2013-08-23 04:44:47 +08:00
|
|
|
bool operator!=(nullptr_t) const TESTS_UNCONSUMED;
|
2013-08-13 05:20:55 +08:00
|
|
|
|
2013-08-30 01:26:57 +08:00
|
|
|
void constCall() const;
|
|
|
|
void nonconstCall();
|
2013-08-13 05:20:55 +08:00
|
|
|
|
2013-08-30 01:26:57 +08:00
|
|
|
void consume() CONSUMES;
|
2013-08-13 05:20:55 +08:00
|
|
|
};
|
|
|
|
|
2013-08-24 02:40:39 +08:00
|
|
|
void baf0(const ConsumableClass<int> var);
|
|
|
|
void baf1(const ConsumableClass<int> &var);
|
|
|
|
void baf2(const ConsumableClass<int> *var);
|
2013-08-13 05:20:55 +08:00
|
|
|
|
2013-10-05 05:28:06 +08:00
|
|
|
void baf3(ConsumableClass<int> &var);
|
|
|
|
void baf4(ConsumableClass<int> *var);
|
|
|
|
void baf5(ConsumableClass<int> &&var);
|
2013-08-13 05:20:55 +08:00
|
|
|
|
2013-09-04 04:11:38 +08:00
|
|
|
ConsumableClass<int> returnsUnconsumed() {
|
|
|
|
return ConsumableClass<int>(); // expected-warning {{return value not in expected state; expected 'unconsumed', observed 'consumed'}}
|
|
|
|
}
|
|
|
|
|
|
|
|
ConsumableClass<int> returnsConsumed() RETURN_TYPESTATE(consumed);
|
|
|
|
ConsumableClass<int> returnsConsumed() {
|
|
|
|
return ConsumableClass<int>();
|
|
|
|
}
|
|
|
|
|
2013-10-05 05:28:06 +08:00
|
|
|
ConsumableClass<int> returnsUnknown() RETURN_TYPESTATE(unknown);
|
|
|
|
|
2013-08-30 01:26:57 +08:00
|
|
|
void testInitialization() {
|
2013-08-24 02:40:39 +08:00
|
|
|
ConsumableClass<int> var0;
|
|
|
|
ConsumableClass<int> var1 = ConsumableClass<int>();
|
2013-08-13 05:20:55 +08:00
|
|
|
|
2013-08-24 02:40:39 +08:00
|
|
|
var0 = ConsumableClass<int>();
|
2013-08-13 05:20:55 +08:00
|
|
|
|
2013-10-05 05:28:06 +08:00
|
|
|
*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}}
|
2013-08-13 05:20:55 +08:00
|
|
|
|
|
|
|
if (var0.isValid()) {
|
|
|
|
*var0;
|
2013-08-30 01:26:57 +08:00
|
|
|
*var1;
|
2013-08-13 05:20:55 +08:00
|
|
|
|
|
|
|
} else {
|
2013-10-05 05:28:06 +08:00
|
|
|
*var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}}
|
2013-08-13 05:20:55 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-24 02:40:39 +08:00
|
|
|
void testTempValue() {
|
2013-10-05 05:28:06 +08:00
|
|
|
*ConsumableClass<int>(); // expected-warning {{invalid invocation of method 'operator*' on a temporary object while it is in the 'consumed' state}}
|
2013-08-23 04:44:47 +08:00
|
|
|
}
|
|
|
|
|
2013-08-30 01:26:57 +08:00
|
|
|
void testSimpleRValueRefs() {
|
2013-08-24 02:40:39 +08:00
|
|
|
ConsumableClass<int> var0;
|
|
|
|
ConsumableClass<int> var1(42);
|
2013-08-13 05:20:55 +08:00
|
|
|
|
2013-10-05 05:28:06 +08:00
|
|
|
*var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}}
|
2013-08-13 05:20:55 +08:00
|
|
|
*var1;
|
|
|
|
|
2013-08-24 02:40:39 +08:00
|
|
|
var0 = static_cast<ConsumableClass<int>&&>(var1);
|
2013-08-13 05:20:55 +08:00
|
|
|
|
|
|
|
*var0;
|
2013-10-05 05:28:06 +08:00
|
|
|
*var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}}
|
2013-08-13 05:20:55 +08:00
|
|
|
}
|
|
|
|
|
2013-08-30 01:26:57 +08:00
|
|
|
void testIfStmt() {
|
2013-08-24 02:40:39 +08:00
|
|
|
ConsumableClass<int> var;
|
2013-08-13 05:20:55 +08:00
|
|
|
|
|
|
|
if (var.isValid()) {
|
2013-08-30 01:26:57 +08:00
|
|
|
*var;
|
2013-08-13 05:20:55 +08:00
|
|
|
} else {
|
2013-10-05 05:28:06 +08:00
|
|
|
*var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
|
2013-08-13 05:20:55 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!var.isValid()) {
|
2013-10-05 05:28:06 +08:00
|
|
|
*var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
|
2013-08-13 05:20:55 +08:00
|
|
|
} else {
|
|
|
|
*var;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (var) {
|
|
|
|
// Empty
|
|
|
|
} else {
|
2013-10-05 05:28:06 +08:00
|
|
|
*var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
|
2013-08-13 05:20:55 +08:00
|
|
|
}
|
2013-08-23 04:44:47 +08:00
|
|
|
|
|
|
|
if (var != nullptr) {
|
|
|
|
// Empty
|
|
|
|
} else {
|
2013-10-05 05:28:06 +08:00
|
|
|
*var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
|
2013-08-23 04:44:47 +08:00
|
|
|
}
|
2013-08-13 05:20:55 +08:00
|
|
|
}
|
|
|
|
|
2013-10-05 05:28:06 +08:00
|
|
|
void testComplexConditionals0() {
|
2013-08-30 01:26:57 +08:00
|
|
|
ConsumableClass<int> var0, var1, var2;
|
|
|
|
|
|
|
|
if (var0 && var1) {
|
|
|
|
*var0;
|
|
|
|
*var1;
|
|
|
|
|
|
|
|
} else {
|
2013-10-05 05:28:06 +08:00
|
|
|
*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}}
|
2013-08-30 01:26:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (var0 || var1) {
|
|
|
|
*var0;
|
|
|
|
*var1;
|
|
|
|
|
|
|
|
} else {
|
2013-10-05 05:28:06 +08:00
|
|
|
*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}}
|
2013-08-30 01:26:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (var0 && !var1) {
|
|
|
|
*var0;
|
|
|
|
*var1;
|
|
|
|
|
|
|
|
} else {
|
2013-10-05 05:28:06 +08:00
|
|
|
*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}}
|
2013-08-30 01:26:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (var0 || !var1) {
|
2013-10-05 05:28:06 +08:00
|
|
|
*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}}
|
2013-08-30 01:26:57 +08:00
|
|
|
|
|
|
|
} else {
|
|
|
|
*var0;
|
|
|
|
*var1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!var0 && !var1) {
|
2013-10-05 05:28:06 +08:00
|
|
|
*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}}
|
2013-08-30 01:26:57 +08:00
|
|
|
|
|
|
|
} else {
|
|
|
|
*var0;
|
|
|
|
*var1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!var0 || !var1) {
|
2013-10-05 05:28:06 +08:00
|
|
|
*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}}
|
2013-08-30 01:26:57 +08:00
|
|
|
|
|
|
|
} else {
|
|
|
|
*var0;
|
|
|
|
*var1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(var0 && var1)) {
|
2013-10-05 05:28:06 +08:00
|
|
|
*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}}
|
2013-08-30 01:26:57 +08:00
|
|
|
|
|
|
|
} else {
|
|
|
|
*var0;
|
|
|
|
*var1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(var0 || var1)) {
|
2013-10-05 05:28:06 +08:00
|
|
|
*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}}
|
2013-08-30 01:26:57 +08:00
|
|
|
|
|
|
|
} else {
|
|
|
|
*var0;
|
|
|
|
*var1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (var0 && var1 && var2) {
|
|
|
|
*var0;
|
|
|
|
*var1;
|
|
|
|
*var2;
|
|
|
|
|
|
|
|
} else {
|
2013-10-05 05:28:06 +08:00
|
|
|
*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}}
|
2013-08-30 01:26:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
// FIXME: Get this test to pass.
|
|
|
|
if (var0 || var1 || var2) {
|
|
|
|
*var0;
|
|
|
|
*var1;
|
|
|
|
*var2;
|
|
|
|
|
|
|
|
} else {
|
2013-10-05 05:28:06 +08:00
|
|
|
*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}}
|
2013-08-30 01:26:57 +08:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void testStateChangeInBranch() {
|
|
|
|
ConsumableClass<int> var;
|
|
|
|
|
|
|
|
// Make var enter the 'unknown' state.
|
2013-10-05 05:28:06 +08:00
|
|
|
baf3(var);
|
2013-08-30 01:26:57 +08:00
|
|
|
|
|
|
|
if (!var) {
|
|
|
|
var = ConsumableClass<int>(42);
|
|
|
|
}
|
|
|
|
|
|
|
|
*var;
|
|
|
|
}
|
|
|
|
|
2013-08-30 06:36:05 +08:00
|
|
|
void testFunctionParam(ConsumableClass<int> param) {
|
|
|
|
|
|
|
|
if (param.isValid()) {
|
|
|
|
*param;
|
|
|
|
} else {
|
2013-09-06 09:28:43 +08:00
|
|
|
*param;
|
2013-08-30 06:36:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
param = nullptr;
|
|
|
|
*param; // expected-warning {{invocation of method 'operator*' on object 'param' while it is in the 'consumed' state}}
|
|
|
|
}
|
|
|
|
|
2013-08-30 01:26:57 +08:00
|
|
|
void testCallingConventions() {
|
2013-08-24 02:40:39 +08:00
|
|
|
ConsumableClass<int> var(42);
|
2013-08-13 05:20:55 +08:00
|
|
|
|
|
|
|
baf0(var);
|
|
|
|
*var;
|
|
|
|
|
|
|
|
baf1(var);
|
|
|
|
*var;
|
|
|
|
|
|
|
|
baf2(&var);
|
|
|
|
*var;
|
|
|
|
|
2013-10-05 05:28:06 +08:00
|
|
|
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> ¶m) {
|
|
|
|
*param; // expected-warning {{invalid invocation of method 'operator*' on object 'param' while it is in the 'unknown' state}}
|
2013-09-04 04:11:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void testReturnStates() {
|
|
|
|
ConsumableClass<int> var;
|
|
|
|
|
|
|
|
var = returnsUnconsumed();
|
|
|
|
*var;
|
|
|
|
|
|
|
|
var = returnsConsumed();
|
2013-10-05 05:28:06 +08:00
|
|
|
*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();
|
2013-08-13 05:20:55 +08:00
|
|
|
}
|
|
|
|
|
2013-08-30 01:26:57 +08:00
|
|
|
void testMoveAsignmentish() {
|
2013-08-24 02:40:39 +08:00
|
|
|
ConsumableClass<int> var0;
|
|
|
|
ConsumableClass<long> var1(42);
|
2013-08-13 05:20:55 +08:00
|
|
|
|
2013-10-05 05:28:06 +08:00
|
|
|
*var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}}
|
2013-08-13 05:20:55 +08:00
|
|
|
*var1;
|
|
|
|
|
2013-08-24 02:40:39 +08:00
|
|
|
var0 = static_cast<ConsumableClass<long>&&>(var1);
|
2013-08-13 05:20:55 +08:00
|
|
|
|
|
|
|
*var0;
|
2013-10-05 05:28:06 +08:00
|
|
|
*var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}}
|
2013-08-30 05:17:25 +08:00
|
|
|
|
|
|
|
var1 = ConsumableClass<long>(42);
|
|
|
|
var1 = nullptr;
|
2013-10-05 05:28:06 +08:00
|
|
|
*var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}}
|
2013-08-13 05:20:55 +08:00
|
|
|
}
|
|
|
|
|
2013-08-30 01:26:57 +08:00
|
|
|
void testConditionalMerge() {
|
2013-08-24 02:40:39 +08:00
|
|
|
ConsumableClass<int> var;
|
2013-08-13 05:20:55 +08:00
|
|
|
|
|
|
|
if (var.isValid()) {
|
|
|
|
// Empty
|
|
|
|
}
|
|
|
|
|
2013-10-05 05:28:06 +08:00
|
|
|
*var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
|
2013-08-13 05:20:55 +08:00
|
|
|
|
|
|
|
if (var.isValid()) {
|
|
|
|
// Empty
|
|
|
|
} else {
|
|
|
|
// Empty
|
|
|
|
}
|
|
|
|
|
2013-10-05 05:28:06 +08:00
|
|
|
*var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
|
2013-08-13 05:20:55 +08:00
|
|
|
}
|
|
|
|
|
2013-08-30 01:26:57 +08:00
|
|
|
void testConsumes0() {
|
2013-08-24 02:40:39 +08:00
|
|
|
ConsumableClass<int> var(42);
|
2013-08-13 05:20:55 +08:00
|
|
|
|
|
|
|
*var;
|
|
|
|
|
|
|
|
var.consume();
|
|
|
|
|
2013-10-05 05:28:06 +08:00
|
|
|
*var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
|
2013-08-13 05:20:55 +08:00
|
|
|
}
|
|
|
|
|
2013-08-30 01:26:57 +08:00
|
|
|
void testConsumes1() {
|
2013-08-24 02:40:39 +08:00
|
|
|
ConsumableClass<int> var(nullptr);
|
2013-08-13 05:20:55 +08:00
|
|
|
|
2013-10-05 05:28:06 +08:00
|
|
|
*var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
|
2013-08-13 05:20:55 +08:00
|
|
|
}
|
|
|
|
|
2013-08-30 01:26:57 +08:00
|
|
|
void testConsumes2() {
|
2013-08-24 02:40:39 +08:00
|
|
|
ConsumableClass<int> var(42);
|
2013-08-23 04:44:47 +08:00
|
|
|
|
|
|
|
var.unconsumedCall();
|
|
|
|
var(6);
|
|
|
|
|
2013-10-05 05:28:06 +08:00
|
|
|
var.unconsumedCall(); // expected-warning {{invalid invocation of method 'unconsumedCall' on object 'var' while it is in the 'consumed' state}}
|
2013-08-23 04:44:47 +08:00
|
|
|
}
|
|
|
|
|
2013-10-05 05:28:06 +08:00
|
|
|
void testUnreachableBlock() {
|
2013-08-30 01:26:57 +08:00
|
|
|
ConsumableClass<int> var(42);
|
|
|
|
|
|
|
|
if (var) {
|
|
|
|
*var;
|
|
|
|
} else {
|
|
|
|
*var;
|
|
|
|
}
|
|
|
|
|
|
|
|
*var;
|
|
|
|
}
|
|
|
|
|
2013-10-10 02:30:24 +08:00
|
|
|
|
|
|
|
void testForLoop1() {
|
|
|
|
ConsumableClass<int> var0, var1(42);
|
2013-08-13 05:20:55 +08:00
|
|
|
|
2013-10-10 02:30:24 +08:00
|
|
|
for (int i = 0; i < 10; ++i) { // expected-warning {{state of variable 'var1' must match at the entry and exit of loop}}
|
|
|
|
*var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}}
|
|
|
|
|
|
|
|
*var1;
|
|
|
|
var1.consume();
|
|
|
|
*var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}}
|
2013-08-13 05:20:55 +08:00
|
|
|
}
|
|
|
|
|
2013-10-10 02:30:24 +08:00
|
|
|
*var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}}
|
2013-08-13 05:20:55 +08:00
|
|
|
}
|
|
|
|
|
2013-10-10 02:30:24 +08:00
|
|
|
void testWhileLoop1() {
|
|
|
|
int i = 10;
|
2013-08-13 05:20:55 +08:00
|
|
|
|
2013-10-10 02:30:24 +08:00
|
|
|
ConsumableClass<int> var0, var1(42);
|
2013-08-13 05:20:55 +08:00
|
|
|
|
2013-10-10 02:30:24 +08:00
|
|
|
while (i-- > 0) {
|
|
|
|
*var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}}
|
|
|
|
|
|
|
|
*var1;
|
|
|
|
var1.consume();
|
|
|
|
*var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}} \
|
|
|
|
// expected-warning {{state of variable 'var1' must match at the entry and exit of loop}}
|
2013-08-13 05:20:55 +08:00
|
|
|
}
|
|
|
|
|
2013-10-10 02:30:24 +08:00
|
|
|
*var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}}
|
2013-08-13 05:20:55 +08:00
|
|
|
}
|