// RUN: %clang_cc1 -fsyntax-only -verify -Wconsumed -std=c++11 %s #define CALLABLE_WHEN_UNCONSUMED __attribute__ ((callable_when_unconsumed)) #define CONSUMES __attribute__ ((consumes)) #define TESTS_UNCONSUMED __attribute__ ((tests_unconsumed)) typedef decltype(nullptr) nullptr_t; template class Bar { T var; public: Bar(void); Bar(nullptr_t p) CONSUMES; Bar(T val); Bar(Bar &other); Bar(Bar &&other); Bar& operator=(Bar &other); Bar& operator=(Bar &&other); Bar& operator=(nullptr_t); template Bar& operator=(Bar &other); template Bar& operator=(Bar &&other); void operator*(void) const CALLABLE_WHEN_UNCONSUMED; bool isValid(void) const TESTS_UNCONSUMED; operator bool() const TESTS_UNCONSUMED; void constCall(void) const; void nonconstCall(void); void consume(void) CONSUMES; }; void baf0(const Bar var); void baf1(const Bar &var); void baf2(const Bar *var); void baf3(Bar &&var); void testInitialization(void) { Bar var0; Bar var1 = Bar(); var0 = Bar(); *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}} if (var0.isValid()) { *var0; *var1; // expected-warning {{invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}} } else { *var0; // expected-warning {{invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} } } void testSimpleRValueRefs(void) { Bar var0; Bar var1(42); *var0; // expected-warning {{invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} *var1; var0 = static_cast&&>(var1); *var0; *var1; // expected-warning {{invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}} } void testIfStmt(void) { Bar var; if (var.isValid()) { // Empty } else { *var; // expected-warning {{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}} } else { *var; } if (var) { // Empty } else { *var; // expected-warning {{invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}} } } void testCallingConventions(void) { Bar var(42); baf0(var); *var; baf1(var); *var; baf2(&var); *var; baf3(static_cast&&>(var)); *var; // expected-warning {{invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}} } void testMoveAsignmentish(void) { Bar var0; Bar var1(42); *var0; // expected-warning {{invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} *var1; var0 = static_cast&&>(var1); *var0; *var1; // expected-warning {{invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}} } void testConditionalMerge(void) { Bar var; if (var.isValid()) { // Empty } *var; if (var.isValid()) { // Empty } else { // Empty } *var; } void testConsumes0(void) { Bar var(42); *var; var.consume(); *var; // expected-warning {{invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}} } void testConsumes1(void) { Bar var(nullptr); *var; // expected-warning {{invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}} } void testSimpleForLoop(void) { Bar var; for (int i = 0; i < 10; ++i) { *var; } *var; } void testSimpleWhileLoop(void) { int i = 0; Bar var; while (i < 10) { *var; ++i; } *var; }