2013-10-18 06:21:03 +08:00
// RUN: %clang_cc1 -fsyntax-only -verify -Wconsumed -fcxx-exceptions -std=c++11 %s
2013-08-13 05:20:55 +08:00
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)))
2013-10-18 07:23:53 +08:00
# define PARAM_TYPESTATE(state) __attribute__ ((param_typestate(state)))
2013-10-05 05:28:06 +08:00
# define RETURN_TYPESTATE(state) __attribute__ ((return_typestate(state)))
2013-10-18 07:23:53 +08:00
# define SET_TYPESTATE(state) __attribute__ ((set_typestate(state)))
2013-10-30 04:28:41 +08:00
# define TEST_TYPESTATE(state) __attribute__ ((test_typestate(state)))
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 ;
2013-10-12 05:55:33 +08:00
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-10-12 07:03:26 +08:00
ConsumableClass < T > & operator = ( nullptr_t ) SET_TYPESTATE ( consumed ) ;
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-10-12 07:03:26 +08:00
void operator ( ) ( int a ) SET_TYPESTATE ( consumed ) ;
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-10-30 04:28:41 +08:00
bool isValid ( ) const TEST_TYPESTATE ( unconsumed ) ;
operator bool ( ) const TEST_TYPESTATE ( unconsumed ) ;
bool operator ! = ( nullptr_t ) const TEST_TYPESTATE ( unconsumed ) ;
bool operator = = ( nullptr_t ) const TEST_TYPESTATE ( consumed ) ;
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-10-12 07:03:26 +08:00
void consume ( ) SET_TYPESTATE ( consumed ) ;
void unconsume ( ) SET_TYPESTATE ( unconsumed ) ;
2013-08-13 05:20:55 +08:00
} ;
2013-10-12 05:55:33 +08:00
class CONSUMABLE ( unconsumed ) DestructorTester {
public :
2014-01-17 07:07:16 +08:00
DestructorTester ( ) ;
2013-10-12 05:55:33 +08:00
DestructorTester ( int ) ;
2019-09-20 07:00:31 +08:00
DestructorTester ( nullptr_t ) RETURN_TYPESTATE ( unconsumed ) ;
DestructorTester ( DestructorTester & & ) ;
2013-10-12 05:55:33 +08:00
2013-10-19 02:36:21 +08:00
void operator * ( ) CALLABLE_WHEN ( " unconsumed " ) ;
2013-10-12 05:55:33 +08:00
~ DestructorTester ( ) CALLABLE_WHEN ( " consumed " ) ;
2019-09-20 07:00:31 +08:00
2013-10-12 05:55:33 +08:00
} ;
2019-09-20 07:00:31 +08:00
void dtByVal ( DestructorTester ) ;
void dtByValMarkUnconsumed ( DestructorTester RETURN_TYPESTATE ( unconsumed ) ) ;
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-19 03:25:18 +08:00
void baf3 ( ConsumableClass < int > var ) ;
void baf4 ( ConsumableClass < int > & var ) ;
void baf5 ( ConsumableClass < int > * var ) ;
void baf6 ( 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 > ( ) ;
2014-01-17 07:07:16 +08:00
ConsumableClass < int > var2 ( 42 ) ;
ConsumableClass < int > var3 ( var2 ) ; // copy constructor
ConsumableClass < int > var4 ( var0 ) ; // copy consumed value
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}}
2014-01-17 07:07:16 +08:00
* 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}}
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-10-12 05:55:33 +08:00
void testDestruction ( ) {
2014-01-17 07:07:16 +08:00
DestructorTester D0 ( 42 ) , D1 ( 42 ) , D2 ;
2013-10-12 05:55:33 +08:00
* D0 ;
* D1 ;
2014-01-17 07:07:16 +08:00
* D2 ; // expected-warning {{invalid invocation of method 'operator*' on object 'D2' while it is in the 'consumed' state}}
2013-10-19 02:36:21 +08:00
2013-10-12 05:55:33 +08:00
D0 . ~ DestructorTester ( ) ; // expected-warning {{invalid invocation of method '~DestructorTester' on object 'D0' while it is in the 'unconsumed' state}}
2013-10-19 02:36:21 +08:00
return ; / / expected - warning { { invalid invocation of method ' ~ DestructorTester ' on object ' D0 ' while it is in the ' unconsumed ' state } } \
2014-01-17 07:07:16 +08:00
expected - warning { { invalid invocation of method ' ~ DestructorTester ' on object ' D1 ' while it is in the ' unconsumed ' state } }
2013-10-12 05:55:33 +08:00
}
2019-09-20 07:00:31 +08:00
void testDestructionByVal ( ) {
{
// both the var and the temporary are consumed:
DestructorTester D0 ( nullptr ) ;
dtByVal ( ( DestructorTester & & ) D0 ) ;
}
{
// the var is consumed but the temporary isn't:
DestructorTester D1 ( nullptr ) ;
dtByValMarkUnconsumed ( ( DestructorTester & & ) D1 ) ; // expected-warning {{invalid invocation of method '~DestructorTester' on a temporary object while it is in the 'unconsumed' state}}
}
}
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-10-12 06:30:48 +08:00
if ( var = = nullptr ) {
* var ; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
} else {
// Empty
}
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.
2013-10-19 03:25:18 +08:00
baf4 ( var0 ) ;
baf4 ( var1 ) ;
baf4 ( var2 ) ;
2013-10-05 05:28:06 +08:00
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-19 03:25:18 +08:00
baf4 ( 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-10-18 06:53:04 +08:00
void 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'}}
if ( cond ) {
Param . consume ( ) ;
return ; // expected-warning {{parameter 'Param' not in expected state when the function returns: expected 'unconsumed', observed 'consumed'}}
}
Param . consume ( ) ;
}
2019-09-20 07:00:31 +08:00
void testRvalueRefParamReturnTypestateCallee ( ConsumableClass < int > & & Param RETURN_TYPESTATE ( unconsumed ) ) {
Param . unconsume ( ) ;
}
2013-10-18 06:53:04 +08:00
void testParamReturnTypestateCaller ( ) {
ConsumableClass < int > var ;
testParamReturnTypestateCallee ( true , var ) ;
2019-09-20 07:00:31 +08:00
testRvalueRefParamReturnTypestateCallee ( ( ConsumableClass < int > & & ) var ) ;
2013-10-18 06:53:04 +08:00
* var ;
}
2013-10-18 07:23:53 +08:00
void testParamTypestateCallee ( ConsumableClass < int > Param0 PARAM_TYPESTATE ( consumed ) ,
ConsumableClass < int > & Param1 PARAM_TYPESTATE ( consumed ) ) {
* Param0 ; // expected-warning {{invalid invocation of method 'operator*' on object 'Param0' while it is in the 'consumed' state}}
* Param1 ; // expected-warning {{invalid invocation of method 'operator*' on object 'Param1' while it is in the 'consumed' state}}
}
void testParamTypestateCaller ( ) {
ConsumableClass < int > Var0 , Var1 ( 42 ) ;
testParamTypestateCallee ( Var0 , Var1 ) ; // expected-warning {{argument not in expected state; expected 'consumed', observed 'unconsumed'}}
}
2014-01-17 07:07:16 +08:00
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'}}
}
2013-10-19 03:25:18 +08:00
void baf3 ( ConsumableClass < int > var ) {
* var ;
}
void baf4 ( ConsumableClass < int > & var ) {
* var ; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'unknown' state}}
}
void baf6 ( ConsumableClass < int > & & var ) {
* var ;
}
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 ;
2019-09-20 07:00:31 +08:00
baf3 ( var ) ;
* var ;
2013-08-13 05:20:55 +08:00
2013-10-19 03:25:18 +08:00
baf4 ( var ) ;
2013-10-05 05:28:06 +08:00
* var ; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'unknown' state}}
var = ConsumableClass < int > ( 42 ) ;
2013-10-19 03:25:18 +08:00
baf5 ( & var ) ;
2013-10-05 05:28:06 +08:00
* var ; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'unknown' state}}
var = ConsumableClass < int > ( 42 ) ;
2013-10-19 03:25:18 +08:00
baf6 ( static_cast < ConsumableClass < int > & & > ( var ) ) ;
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 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}}
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 ;
2013-10-19 03:25:18 +08:00
baf4 ( var ) ;
2013-10-05 05:28:06 +08:00
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-10-12 07:03:26 +08:00
void testSetTypestate ( ) {
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-10-12 07:03:26 +08:00
var . unconsume ( ) ;
* var ;
2013-08-13 05:20:55 +08:00
}
2013-10-12 07:03:26 +08:00
void testConsumes0 ( ) {
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-10-12 07:03:26 +08:00
void testConsumes1 ( ) {
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-18 02:19:31 +08:00
while ( i - - > 0 ) { // expected-warning {{state of variable 'var1' must match at the entry and exit of loop}}
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}}
* var1 ;
var1 . consume ( ) ;
2013-10-18 02:19:31 +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-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-18 02:19:31 +08:00
2015-04-16 06:32:44 +08:00
// Tests if state information is correctly discarded for certain shapes of CFGs.
void testSwitchGOTO ( void ) {
int a ;
LABEL0 :
switch ( a )
case 0 :
goto LABEL0 ;
goto LABEL0 ;
}
2013-11-08 02:35:18 +08:00
typedef const int * & IntegerPointerReference ;
void testIsRValueRefishAndCanonicalType ( IntegerPointerReference a ) { }
2013-10-18 02:19:31 +08:00
namespace ContinueICETest {
bool cond1 ( ) ;
bool cond2 ( ) ;
static void foo1 ( ) {
while ( cond1 ( ) ) {
if ( cond2 ( ) )
continue ;
}
}
static void foo2 ( ) {
while ( true ) {
if ( false )
continue ;
}
}
2013-10-18 06:21:03 +08:00
class runtime_error
{
public :
virtual ~ runtime_error ( ) ;
} ;
void read ( bool sf ) {
while ( sf ) {
if ( sf ) throw runtime_error ( ) ;
}
}
2013-10-18 02:19:31 +08:00
} // end namespace ContinueICETest
2013-10-19 07:11:49 +08:00
2014-01-14 08:36:53 +08:00
namespace StatusUseCaseTests {
2013-10-19 07:11:49 +08:00
2014-01-14 08:36:53 +08:00
class CONSUMABLE ( unconsumed )
__attribute__ ( ( consumable_auto_cast_state ) )
__attribute__ ( ( consumable_set_state_on_read ) )
Status {
2013-10-19 07:11:49 +08:00
int code ;
public :
2014-03-21 04:39:20 +08:00
static Status OK ;
2013-10-19 07:11:49 +08:00
Status ( ) RETURN_TYPESTATE ( consumed ) ;
Status ( int c ) RETURN_TYPESTATE ( unconsumed ) ;
Status ( const Status & other ) ;
2013-11-16 08:22:43 +08:00
Status ( Status & & other ) ;
2013-10-19 07:11:49 +08:00
Status & operator = ( const Status & other ) CALLABLE_WHEN ( " unknown " , " consumed " ) ;
2013-11-16 08:22:43 +08:00
Status & operator = ( Status & & other ) CALLABLE_WHEN ( " unknown " , " consumed " ) ;
2013-10-19 07:11:49 +08:00
2014-03-21 04:39:20 +08:00
bool operator = = ( const Status & other ) const SET_TYPESTATE ( consumed ) ;
2013-10-19 07:11:49 +08:00
bool check ( ) const SET_TYPESTATE ( consumed ) ;
void ignore ( ) const SET_TYPESTATE ( consumed ) ;
// Status& markAsChecked() { return *this; }
void clear ( ) CALLABLE_WHEN ( " unknown " , " consumed " ) SET_TYPESTATE ( consumed ) ;
~ Status ( ) CALLABLE_WHEN ( " unknown " , " consumed " ) ;
2014-05-08 19:50:00 +08:00
operator bool ( ) const ; // Will not consume the object.
2013-10-19 07:11:49 +08:00
} ;
bool cond ( ) ;
Status doSomething ( ) ;
2013-11-16 08:22:43 +08:00
void handleStatus ( const Status & s RETURN_TYPESTATE ( consumed ) ) ;
2014-01-14 08:36:53 +08:00
void handleStatusRef ( Status & s ) ;
void handleStatusPtr ( Status * s ) ;
void handleStatusUnmarked ( const Status & s ) ;
2013-10-19 07:11:49 +08:00
2014-03-21 04:39:20 +08:00
void log ( const char * msg ) ;
void fail ( ) __attribute__ ( ( noreturn ) ) ;
void checkStat ( const Status & s ) ;
2013-11-16 08:22:43 +08:00
void testSimpleTemporaries0 ( ) {
doSomething ( ) ; // expected-warning {{invalid invocation of method '~Status' on a temporary object while it is in the 'unconsumed' state}}
}
void testSimpleTemporaries1 ( ) {
doSomething ( ) . ignore ( ) ;
}
void testSimpleTemporaries2 ( ) {
handleStatus ( doSomething ( ) ) ;
}
void testSimpleTemporaries3 ( ) {
Status s = doSomething ( ) ;
} // expected-warning {{invalid invocation of method '~Status' on object 's' while it is in the 'unconsumed' state}}
2014-05-08 19:50:00 +08:00
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}}
}
2014-01-14 08:36:53 +08:00
Status testSimpleTemporariesReturn0 ( ) {
return doSomething ( ) ;
}
Status testSimpleTemporariesReturn1 ( ) {
Status s = doSomething ( ) ;
return s ;
}
2013-11-16 08:22:43 +08:00
void testSimpleTemporaries4 ( ) {
Status s = doSomething ( ) ;
s . check ( ) ;
}
void testSimpleTemporaries5 ( ) {
Status s = doSomething ( ) ;
s . clear ( ) ; // expected-warning {{invalid invocation of method 'clear' on object 's' while it is in the 'unconsumed' state}}
}
void testSimpleTemporaries6 ( ) {
2014-01-14 08:36:53 +08:00
Status s1 = doSomething ( ) ;
handleStatus ( s1 ) ;
Status s2 = doSomething ( ) ;
handleStatusRef ( s2 ) ;
Status s3 = doSomething ( ) ;
handleStatusPtr ( & s3 ) ;
Status s4 = doSomething ( ) ;
handleStatusUnmarked ( s4 ) ;
2013-11-16 08:22:43 +08:00
}
void testSimpleTemporaries7 ( ) {
Status s ;
s = doSomething ( ) ;
} // expected-warning {{invalid invocation of method '~Status' on object 's' while it is in the 'unconsumed' state}}
void testTemporariesWithConditionals0 ( ) {
int a ;
Status s = doSomething ( ) ;
if ( cond ( ) ) a = 0 ;
else a = 1 ;
} // expected-warning {{invalid invocation of method '~Status' on object 's' while it is in the 'unconsumed' state}}
void testTemporariesWithConditionals1 ( ) {
int a ;
Status s = doSomething ( ) ;
if ( cond ( ) ) a = 0 ;
else a = 1 ;
s . ignore ( ) ;
}
2013-10-19 07:11:49 +08:00
2013-11-16 08:22:43 +08:00
void testTemporariesWithConditionals2 ( ) {
int a ;
Status s = doSomething ( ) ;
s . ignore ( ) ;
if ( cond ( ) ) a = 0 ;
else a = 1 ;
}
2013-10-19 07:11:49 +08:00
2013-11-16 08:22:43 +08:00
void testTemporariesWithConditionals3 ( ) {
Status s = doSomething ( ) ;
2013-10-19 07:11:49 +08:00
if ( cond ( ) ) {
2013-11-16 08:22:43 +08:00
s . check ( ) ;
2013-10-19 07:11:49 +08:00
}
}
2013-11-16 08:22:43 +08:00
void testTemporariesAndConstructors0 ( ) {
2014-01-14 08:36:53 +08:00
Status s ( doSomething ( ) ) ; // Test the copy constructor.
2013-11-16 08:22:43 +08:00
s . check ( ) ;
}
2014-01-14 08:36:53 +08:00
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.
2013-11-16 08:22:43 +08:00
Status s2 ( s1 ) ;
s2 . check ( ) ;
2014-01-14 08:36:53 +08:00
}
2013-11-16 08:22:43 +08:00
2014-01-14 08:36:53 +08:00
void testTemporariesAndConstructors2F ( ) {
2013-11-16 08:22:43 +08:00
// Test the move constructor.
Status s1 = doSomething ( ) ;
2014-01-14 08:36:53 +08:00
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 ) ;
2013-11-16 08:22:43 +08:00
s2 . check ( ) ;
}
2014-01-14 08:36:53 +08:00
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 ( ) {
2013-11-16 08:22:43 +08:00
// Test the assignment operator.
Status s1 = doSomething ( ) ;
Status s2 ;
s2 = s1 ;
s2 . check ( ) ;
2014-01-14 08:36:53 +08:00
}
2013-11-16 08:22:43 +08:00
2014-01-14 08:36:53 +08:00
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 ( ) {
2013-11-16 08:22:43 +08:00
// Test the move assignment operator.
Status s1 = doSomething ( ) ;
Status s2 ;
s2 = static_cast < Status & & > ( s1 ) ;
s2 . check ( ) ;
}
void testTemporariesAndOperators2 ( ) {
Status s1 = doSomething ( ) ;
Status s2 = doSomething ( ) ;
s1 = s2 ; // expected-warning {{invalid invocation of method 'operator=' on object 's1' while it is in the 'unconsumed' state}}
s1 . check ( ) ;
s2 . check ( ) ;
}
2014-01-14 08:36:53 +08:00
Status testReturnAutocast ( ) {
Status s = doSomething ( ) ;
s . check ( ) ; // consume s
return s ; // should autocast back to unconsumed
}
2014-03-21 04:39:20 +08:00
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
2013-10-19 07:11:49 +08:00
} // end namespace InitializerAssertionFailTest
2013-12-17 05:41:30 +08:00
namespace std {
void move ( ) ;
template < class T >
void move ( T & & ) ;
2013-12-17 08:40:40 +08:00
namespace __1 {
void move ( ) ;
template < class T >
void move ( T & & ) ;
}
2013-12-17 05:41:30 +08:00
}
namespace PR18260 {
class X {
public :
void move ( ) ;
} x ;
void test ( ) {
x . move ( ) ;
std : : move ( ) ;
std : : move ( x ) ;
2013-12-17 08:40:40 +08:00
std : : __1 : : move ( ) ;
std : : __1 : : move ( x ) ;
2013-12-17 05:41:30 +08:00
}
} // end namespace PR18260
2014-03-21 04:39:20 +08:00