head	1.1;
branch	1.1.1;
access;
symbols
	netbsd-11-0-RC4:1.1.1.7
	netbsd-11-0-RC3:1.1.1.7
	netbsd-11-0-RC2:1.1.1.7
	netbsd-11-0-RC1:1.1.1.7
	perseant-exfatfs-base-20250801:1.1.1.7
	netbsd-11:1.1.1.7.0.10
	netbsd-11-base:1.1.1.7
	netbsd-10-1-RELEASE:1.1.1.7
	perseant-exfatfs-base-20240630:1.1.1.7
	perseant-exfatfs:1.1.1.7.0.8
	perseant-exfatfs-base:1.1.1.7
	netbsd-8-3-RELEASE:1.1.1.6
	netbsd-9-4-RELEASE:1.1.1.6
	netbsd-10-0-RELEASE:1.1.1.7
	netbsd-10-0-RC6:1.1.1.7
	netbsd-10-0-RC5:1.1.1.7
	netbsd-10-0-RC4:1.1.1.7
	netbsd-10-0-RC3:1.1.1.7
	netbsd-10-0-RC2:1.1.1.7
	netbsd-10-0-RC1:1.1.1.7
	netbsd-10:1.1.1.7.0.6
	netbsd-10-base:1.1.1.7
	netbsd-9-3-RELEASE:1.1.1.6
	cjep_sun2x:1.1.1.7.0.4
	cjep_sun2x-base:1.1.1.7
	cjep_staticlib_x-base1:1.1.1.7
	netbsd-9-2-RELEASE:1.1.1.6
	cjep_staticlib_x:1.1.1.7.0.2
	cjep_staticlib_x-base:1.1.1.7
	netbsd-9-1-RELEASE:1.1.1.6
	phil-wifi-20200421:1.1.1.7
	phil-wifi-20200411:1.1.1.7
	phil-wifi-20200406:1.1.1.7
	netbsd-8-2-RELEASE:1.1.1.6
	netbsd-9-0-RELEASE:1.1.1.6
	netbsd-9-0-RC2:1.1.1.6
	netbsd-9-0-RC1:1.1.1.6
	netbsd-9:1.1.1.6.0.18
	netbsd-9-base:1.1.1.6
	phil-wifi-20190609:1.1.1.6
	netbsd-8-1-RELEASE:1.1.1.6
	netbsd-8-1-RC1:1.1.1.6
	pgoyette-compat-merge-20190127:1.1.1.6
	pgoyette-compat-20190127:1.1.1.6
	pgoyette-compat-20190118:1.1.1.6
	pgoyette-compat-1226:1.1.1.6
	pgoyette-compat-1126:1.1.1.6
	pgoyette-compat-1020:1.1.1.6
	pgoyette-compat-0930:1.1.1.6
	pgoyette-compat-0906:1.1.1.6
	netbsd-7-2-RELEASE:1.1.1.5
	pgoyette-compat-0728:1.1.1.6
	clang-337282:1.1.1.6
	netbsd-8-0-RELEASE:1.1.1.6
	phil-wifi:1.1.1.6.0.16
	phil-wifi-base:1.1.1.6
	pgoyette-compat-0625:1.1.1.6
	netbsd-8-0-RC2:1.1.1.6
	pgoyette-compat-0521:1.1.1.6
	pgoyette-compat-0502:1.1.1.6
	pgoyette-compat-0422:1.1.1.6
	netbsd-8-0-RC1:1.1.1.6
	pgoyette-compat-0415:1.1.1.6
	pgoyette-compat-0407:1.1.1.6
	pgoyette-compat-0330:1.1.1.6
	pgoyette-compat-0322:1.1.1.6
	pgoyette-compat-0315:1.1.1.6
	netbsd-7-1-2-RELEASE:1.1.1.5
	pgoyette-compat:1.1.1.6.0.14
	pgoyette-compat-base:1.1.1.6
	netbsd-7-1-1-RELEASE:1.1.1.5
	clang-319952:1.1.1.6
	matt-nb8-mediatek:1.1.1.6.0.12
	matt-nb8-mediatek-base:1.1.1.6
	clang-309604:1.1.1.6
	perseant-stdc-iso10646:1.1.1.6.0.10
	perseant-stdc-iso10646-base:1.1.1.6
	netbsd-8:1.1.1.6.0.8
	netbsd-8-base:1.1.1.6
	prg-localcount2-base3:1.1.1.6
	prg-localcount2-base2:1.1.1.6
	prg-localcount2-base1:1.1.1.6
	prg-localcount2:1.1.1.6.0.6
	prg-localcount2-base:1.1.1.6
	pgoyette-localcount-20170426:1.1.1.6
	bouyer-socketcan-base1:1.1.1.6
	pgoyette-localcount-20170320:1.1.1.6
	netbsd-7-1:1.1.1.5.0.10
	netbsd-7-1-RELEASE:1.1.1.5
	netbsd-7-1-RC2:1.1.1.5
	clang-294123:1.1.1.6
	netbsd-7-nhusb-base-20170116:1.1.1.5
	bouyer-socketcan:1.1.1.6.0.4
	bouyer-socketcan-base:1.1.1.6
	clang-291444:1.1.1.6
	pgoyette-localcount-20170107:1.1.1.6
	netbsd-7-1-RC1:1.1.1.5
	pgoyette-localcount-20161104:1.1.1.6
	netbsd-7-0-2-RELEASE:1.1.1.5
	localcount-20160914:1.1.1.6
	netbsd-7-nhusb:1.1.1.5.0.8
	netbsd-7-nhusb-base:1.1.1.5
	clang-280599:1.1.1.6
	pgoyette-localcount-20160806:1.1.1.6
	pgoyette-localcount-20160726:1.1.1.6
	pgoyette-localcount:1.1.1.6.0.2
	pgoyette-localcount-base:1.1.1.6
	netbsd-7-0-1-RELEASE:1.1.1.5
	clang-261930:1.1.1.6
	netbsd-7-0:1.1.1.5.0.6
	netbsd-7-0-RELEASE:1.1.1.5
	netbsd-7-0-RC3:1.1.1.5
	netbsd-7-0-RC2:1.1.1.5
	netbsd-7-0-RC1:1.1.1.5
	clang-237755:1.1.1.5
	clang-232565:1.1.1.5
	clang-227398:1.1.1.5
	tls-maxphys-base:1.1.1.5
	tls-maxphys:1.1.1.5.0.4
	netbsd-7:1.1.1.5.0.2
	netbsd-7-base:1.1.1.5
	clang-215315:1.1.1.5
	clang-209886:1.1.1.5
	yamt-pagecache:1.1.1.4.0.4
	yamt-pagecache-base9:1.1.1.4
	tls-earlyentropy:1.1.1.4.0.2
	tls-earlyentropy-base:1.1.1.5
	riastradh-xf86-video-intel-2-7-1-pre-2-21-15:1.1.1.4
	riastradh-drm2-base3:1.1.1.4
	clang-202566:1.1.1.4
	clang-201163:1.1.1.4
	clang-199312:1.1.1.3
	clang-198450:1.1.1.2
	clang-196603:1.1.1.1
	clang-195771:1.1.1.1
	LLVM:1.1.1;
locks; strict;
comment	@// @;


1.1
date	2013.11.28.14.14.56;	author joerg;	state Exp;
branches
	1.1.1.1;
next	;
commitid	ow8OybrawrB1f3fx;

1.1.1.1
date	2013.11.28.14.14.56;	author joerg;	state Exp;
branches;
next	1.1.1.2;
commitid	ow8OybrawrB1f3fx;

1.1.1.2
date	2014.01.05.15.40.34;	author joerg;	state Exp;
branches;
next	1.1.1.3;
commitid	wh3aCSIWykURqWjx;

1.1.1.3
date	2014.01.15.21.26.05;	author joerg;	state Exp;
branches;
next	1.1.1.4;
commitid	NQXlzzA0SPkc5glx;

1.1.1.4
date	2014.02.14.20.07.41;	author joerg;	state Exp;
branches
	1.1.1.4.2.1
	1.1.1.4.4.1;
next	1.1.1.5;
commitid	annVkZ1sc17rF6px;

1.1.1.5
date	2014.05.30.18.14.49;	author joerg;	state Exp;
branches
	1.1.1.5.4.1;
next	1.1.1.6;
commitid	8q0kdlBlCn09GACx;

1.1.1.6
date	2016.02.27.22.10.16;	author joerg;	state Exp;
branches
	1.1.1.6.16.1;
next	1.1.1.7;
commitid	tIimz3oDlh1NpBWy;

1.1.1.7
date	2019.11.13.22.22.56;	author joerg;	state dead;
branches;
next	;
commitid	QD8YATxuNG34YJKB;

1.1.1.4.2.1
date	2014.08.10.07.08.23;	author tls;	state Exp;
branches;
next	;
commitid	t01A1TLTYxkpGMLx;

1.1.1.4.4.1
date	2014.02.14.20.07.41;	author yamt;	state dead;
branches;
next	1.1.1.4.4.2;
commitid	WSrDtL5nYAUyiyBx;

1.1.1.4.4.2
date	2014.05.22.16.19.41;	author yamt;	state Exp;
branches;
next	;
commitid	WSrDtL5nYAUyiyBx;

1.1.1.5.4.1
date	2014.05.30.18.14.49;	author tls;	state dead;
branches;
next	1.1.1.5.4.2;
commitid	jTnpym9Qu0o4R1Nx;

1.1.1.5.4.2
date	2014.08.19.23.49.20;	author tls;	state Exp;
branches;
next	;
commitid	jTnpym9Qu0o4R1Nx;

1.1.1.6.16.1
date	2020.04.13.07.50.23;	author martin;	state dead;
branches;
next	;
commitid	X01YhRUPVUDaec4C;


desc
@@


1.1
log
@Initial revision
@
text
@// RUN: %clang_cc1 -fsyntax-only -verify -Wconsumed -fcxx-exceptions -std=c++11 %s

// TODO: Switch to using macros for the expected warnings.

#define CALLABLE_WHEN(...)      __attribute__ ((callable_when(__VA_ARGS__)))
#define CONSUMABLE(state)       __attribute__ ((consumable(state)))
#define PARAM_TYPESTATE(state)  __attribute__ ((param_typestate(state)))
#define RETURN_TYPESTATE(state) __attribute__ ((return_typestate(state)))
#define SET_TYPESTATE(state)    __attribute__ ((set_typestate(state)))
#define TEST_TYPESTATE(state)   __attribute__ ((test_typestate(state)))

typedef decltype(nullptr) nullptr_t;

template <typename T>
class CONSUMABLE(unconsumed) ConsumableClass {
  T var;
  
public:
  ConsumableClass();
  ConsumableClass(nullptr_t p) RETURN_TYPESTATE(consumed);
  ConsumableClass(T val) RETURN_TYPESTATE(unconsumed);
  ConsumableClass(ConsumableClass<T> &other);
  ConsumableClass(ConsumableClass<T> &&other);
  
  ConsumableClass<T>& operator=(ConsumableClass<T>  &other);
  ConsumableClass<T>& operator=(ConsumableClass<T> &&other);
  ConsumableClass<T>& operator=(nullptr_t) SET_TYPESTATE(consumed);
  
  template <typename U>
  ConsumableClass<T>& operator=(ConsumableClass<U>  &other);
  
  template <typename U>
  ConsumableClass<T>& operator=(ConsumableClass<U> &&other);
  
  void operator()(int a) SET_TYPESTATE(consumed);
  void operator*() const CALLABLE_WHEN("unconsumed");
  void unconsumedCall() const CALLABLE_WHEN("unconsumed");
  void callableWhenUnknown() const CALLABLE_WHEN("unconsumed", "unknown");
  
  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);
  
  void constCall() const;
  void nonconstCall();
  
  void consume() SET_TYPESTATE(consumed);
  void unconsume() SET_TYPESTATE(unconsumed);
};

class CONSUMABLE(unconsumed) DestructorTester {
public:
  DestructorTester() RETURN_TYPESTATE(unconsumed);
  DestructorTester(int);
  
  void operator*() CALLABLE_WHEN("unconsumed");
  
  ~DestructorTester() CALLABLE_WHEN("consumed");
};

void baf0(const ConsumableClass<int>  var);
void baf1(const ConsumableClass<int> &var);
void baf2(const ConsumableClass<int> *var);

void baf3(ConsumableClass<int>   var);
void baf4(ConsumableClass<int>  &var);
void baf5(ConsumableClass<int>  *var);
void baf6(ConsumableClass<int> &&var);

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>();
}

ConsumableClass<int> returnsUnknown() RETURN_TYPESTATE(unknown);

void testInitialization() {
  ConsumableClass<int> var0;
  ConsumableClass<int> var1 = ConsumableClass<int>();
  
  var0 = ConsumableClass<int>();
  
  *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 {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}}
  }
}

void testDestruction() {
  DestructorTester D0(42), D1(42);
  
  *D0;
  *D1;
  
  DestructorTester D2;
  *D2;
  
  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}}
}

void testTempValue() {
  *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 {{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 {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}}
}

void testIfStmt() {
  ConsumableClass<int> var;
  
  if (var.isValid()) {
    *var;
  } else {
    *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
  }
  
  if (!var.isValid()) {
    *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
  } else {
    *var;
  }
  
  if (var) {
    // Empty
  } else {
    *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 {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
  }
  
  if (var == nullptr) {
    *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
  } else {
    // Empty
  }
}

void testComplexConditionals0() {
  ConsumableClass<int> var0, var1, var2;
  
  if (var0 && var1) {
    *var0;
    *var1;
    
  } 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;
    
  } 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;
    
  } 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; // 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;
    *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;
    *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;
    *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;
    *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;
    *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 '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
  // FIXME: Get this test to pass.
  if (var0 || var1 || var2) {
    *var0;
    *var1;
    *var2;
    
  } 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
}

void testComplexConditionals1() {
  ConsumableClass<int> var0, var1, var2;
  
  // Coerce all variables into the unknown state.
  baf4(var0);
  baf4(var1);
  baf4(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
}

void testStateChangeInBranch() {
  ConsumableClass<int> var;
  
  // Make var enter the 'unknown' state.
  baf4(var);
  
  if (!var) {
    var = ConsumableClass<int>(42);
  }
  
  *var;
}

void testFunctionParam(ConsumableClass<int> param) {
  
  if (param.isValid()) {
    *param;
  } else {
    *param;
  }
  
  param = nullptr;
  *param; // expected-warning {{invocation of method 'operator*' on object 'param' while it is in the 'consumed' state}}
}

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();
}

void testParamReturnTypestateCaller() {
  ConsumableClass<int> var;
  
  testParamReturnTypestateCallee(true, var);
  
  *var;
}

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'}}
}

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;
}

void testCallingConventions() {
  ConsumableClass<int> var(42);
  
  baf0(var);  
  *var;
  
  baf1(var);  
  *var;
  
  baf2(&var);  
  *var;
  
  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(&var);  
  *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'unknown' state}}
  
  var = ConsumableClass<int>(42);
  baf6(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() {
  ConsumableClass<int> var;
  
  var = returnsUnconsumed();
  *var;
  
  var = returnsConsumed();
  *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;
  
  baf4(var);
  
  var.callableWhenUnknown();
}

void testMoveAsignmentish() {
  ConsumableClass<int>  var0;
  ConsumableClass<long> var1(42);
  
  *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 {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}}
  
  var1 = ConsumableClass<long>(42);
  var1 = nullptr;
  *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}}
}

void testConditionalMerge() {
  ConsumableClass<int> var;
  
  if (var.isValid()) {
    // Empty
  }
  
  *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
  
  if (var.isValid()) {
    // Empty
  } else {
    // Empty
  }
  
  *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
}

void testSetTypestate() {
  ConsumableClass<int> var(42);
  
  *var;
  
  var.consume();
  
  *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
  
  var.unconsume();
  
  *var;
}

void testConsumes0() {
  ConsumableClass<int> var(nullptr);
  
  *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
}

void testConsumes1() {
  ConsumableClass<int> var(42);
  
  var.unconsumedCall();
  var(6);
  
  var.unconsumedCall(); // expected-warning {{invalid invocation of method 'unconsumedCall' on object 'var' while it is in the 'consumed' state}}
}

void testUnreachableBlock() {
  ConsumableClass<int> var(42);
  
  if (var) {
    *var;
  } else {
    *var;
  }
  
  *var;
}


void testForLoop1() {
  ConsumableClass<int> var0, var1(42);
  
  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}}
  }
  
  *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}}
}

void testWhileLoop1() {
  int i = 10;
  
  ConsumableClass<int> var0, var1(42);
  
  while (i-- > 0) { // 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}}
  }
  
  *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}}
}

typedef const int*& IntegerPointerReference;
void testIsRValueRefishAndCanonicalType(IntegerPointerReference a) {}

namespace ContinueICETest {

bool cond1();
bool cond2();

static void foo1() {
  while (cond1()) {
    if (cond2())
      continue;
  }
}

static void foo2() {
  while (true) {
    if (false)
      continue;
  }
}

class runtime_error
{
public:
  virtual ~runtime_error();
};

void read(bool sf) {
    while (sf) {
        if(sf) throw runtime_error();
    }
}

} // end namespace ContinueICETest


namespace InitializerAssertionFailTest {

class CONSUMABLE(unconsumed) Status {
  int code;

public:
  Status() RETURN_TYPESTATE(consumed);
  Status(int c) RETURN_TYPESTATE(unconsumed);

  Status(const Status &other);
  Status(Status &&other);

  Status& operator=(const Status &other) CALLABLE_WHEN("unknown", "consumed");
  Status& operator=(Status &&other) CALLABLE_WHEN("unknown", "consumed");

  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");
};


bool   cond();
Status doSomething();
void   handleStatus(const Status& s RETURN_TYPESTATE(consumed));
void   handleStatusPtr(const Status* s);

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}}

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() {
  Status s = doSomething();
  handleStatus(s);
}

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();
}

void testTemporariesWithConditionals2() {
  int a;
  
  Status s = doSomething();
  s.ignore();
  if (cond()) a = 0;
  else        a = 1;
}

void testTemporariesWithConditionals3() {
  Status s = doSomething();
  if (cond()) {
    s.check();
  }
}

void testTemporariesAndConstructors0() {
  Status s(doSomething());
  s.check();
}

void testTemporariesAndConstructors1() {
  // Test the copy constructor.
  
  Status s1 = doSomething();
  Status s2(s1);
  s2.check();
}  // expected-warning {{invalid invocation of method '~Status' on object 's1' while it is in the 'unconsumed' state}}

void testTemporariesAndConstructors2() {
  // Test the move constructor.
  
  Status s1 = doSomething();
  Status s2(static_cast<Status&&>(s1));
  s2.check();
}

void testTemporariesAndOperators0() {
  // 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() {
  // 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();
}

} // end namespace InitializerAssertionFailTest

@


1.1.1.1
log
@Import Clang 3.4rc1 r195771.
@
text
@@


1.1.1.2
log
@Import clang 3.5svn r198450.
@
text
@a795 27

namespace std {
  void move();
  template<class T>
  void move(T&&);

  namespace __1 {
    void move();
    template<class T>
    void move(T&&);
  }
}

namespace PR18260 {
  class X {
    public:
      void move();
  } x;

  void test() {
    x.move();
    std::move();
    std::move(x);
    std::__1::move();
    std::__1::move(x);
  }
} // end namespace PR18260
@


1.1.1.3
log
@Import Clang 3.5svn r199312
@
text
@d648 1
a648 1
namespace StatusUseCaseTests {
d650 1
a650 4
class CONSUMABLE(unconsumed)
      __attribute__((consumable_auto_cast_state))
      __attribute__((consumable_set_state_on_read))
    Status {
d676 1
a676 3
void   handleStatusRef(Status& s);
void   handleStatusPtr(Status* s);
void   handleStatusUnmarked(const Status& s);
a693 9
Status testSimpleTemporariesReturn0() {
  return doSomething();
}

Status testSimpleTemporariesReturn1() {
  Status s = doSomething();
  return s;
}

d705 2
a706 11
  Status s1 = doSomething();
  handleStatus(s1);

  Status s2 = doSomething();
  handleStatusRef(s2);

  Status s3 = doSomething();
  handleStatusPtr(&s3);

  Status s4 = doSomething();
  handleStatusUnmarked(s4);
d748 1
a748 1
  Status s(doSomething());    // Test the copy constructor.
d752 4
a755 7
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.
d758 1
a758 1
}
d760 1
a760 1
void testTemporariesAndConstructors2F() {
d762 1
d764 1
a764 7
  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);
d768 1
a768 8
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() {
d770 1
d775 1
a775 1
}
d777 1
a777 8
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() {
d779 1
a793 6
Status testReturnAutocast() {
  Status s = doSomething();
  s.check();  // consume s
  return s;   // should autocast back to unconsumed
}

@


1.1.1.4
log
@Import Clang 3.5svn r201163.
@
text
@d54 1
a54 1
  DestructorTester();
d85 3
a87 4
  ConsumableClass<int> var2(42);
  ConsumableClass<int> var3(var2);  // copy constructor
  ConsumableClass<int> var4(var0);  // copy consumed value

a89 9
  *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}}
d101 1
a101 1
  DestructorTester D0(42), D1(42), D2;
d105 3
a107 1
  *D2; // expected-warning {{invalid invocation of method 'operator*' on object 'D2' while it is in the 'consumed' state}}
d112 2
a113 1
             expected-warning {{invalid invocation of method '~DestructorTester' on object 'D1' while it is in the 'unconsumed' state}}
a429 23

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'}}
}

@


1.1.1.4.2.1
log
@Rebase.
@
text
@a686 2
  static Status OK;

a695 2
  bool operator==(const Status &other) const SET_TYPESTATE(consumed);

a702 2

  operator bool() const; // Will not consume the object.
a712 5
void   log(const char* msg);
void   fail() __attribute__((noreturn));
void   checkStat(const Status& s);


a728 4
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}}
}

a872 23

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

a901 1

@


1.1.1.5
log
@Import Clang 3.5svn r209886.
@
text
@a686 2
  static Status OK;

a695 2
  bool operator==(const Status &other) const SET_TYPESTATE(consumed);

a702 2

  operator bool() const; // Will not consume the object.
a712 5
void   log(const char* msg);
void   fail() __attribute__((noreturn));
void   checkStat(const Status& s);


a728 4
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}}
}

a872 23

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

a901 1

@


1.1.1.6
log
@Import Clang 3.8.0rc3 r261930.
@
text
@a640 12
// 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;
}

@


1.1.1.6.16.1
log
@Mostly merge changes from HEAD upto 20200411
@
text
@@


1.1.1.7
log
@Mark old LLVM instance as dead.
@
text
@@


1.1.1.5.4.1
log
@file warn-consumed-analysis.cpp was added on branch tls-maxphys on 2014-08-19 23:49:20 +0000
@
text
@d1 940
@


1.1.1.5.4.2
log
@Rebase to HEAD as of a few days ago.
@
text
@a0 940
// RUN: %clang_cc1 -fsyntax-only -verify -Wconsumed -fcxx-exceptions -std=c++11 %s

// TODO: Switch to using macros for the expected warnings.

#define CALLABLE_WHEN(...)      __attribute__ ((callable_when(__VA_ARGS__)))
#define CONSUMABLE(state)       __attribute__ ((consumable(state)))
#define PARAM_TYPESTATE(state)  __attribute__ ((param_typestate(state)))
#define RETURN_TYPESTATE(state) __attribute__ ((return_typestate(state)))
#define SET_TYPESTATE(state)    __attribute__ ((set_typestate(state)))
#define TEST_TYPESTATE(state)   __attribute__ ((test_typestate(state)))

typedef decltype(nullptr) nullptr_t;

template <typename T>
class CONSUMABLE(unconsumed) ConsumableClass {
  T var;
  
public:
  ConsumableClass();
  ConsumableClass(nullptr_t p) RETURN_TYPESTATE(consumed);
  ConsumableClass(T val) RETURN_TYPESTATE(unconsumed);
  ConsumableClass(ConsumableClass<T> &other);
  ConsumableClass(ConsumableClass<T> &&other);
  
  ConsumableClass<T>& operator=(ConsumableClass<T>  &other);
  ConsumableClass<T>& operator=(ConsumableClass<T> &&other);
  ConsumableClass<T>& operator=(nullptr_t) SET_TYPESTATE(consumed);
  
  template <typename U>
  ConsumableClass<T>& operator=(ConsumableClass<U>  &other);
  
  template <typename U>
  ConsumableClass<T>& operator=(ConsumableClass<U> &&other);
  
  void operator()(int a) SET_TYPESTATE(consumed);
  void operator*() const CALLABLE_WHEN("unconsumed");
  void unconsumedCall() const CALLABLE_WHEN("unconsumed");
  void callableWhenUnknown() const CALLABLE_WHEN("unconsumed", "unknown");
  
  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);
  
  void constCall() const;
  void nonconstCall();
  
  void consume() SET_TYPESTATE(consumed);
  void unconsume() SET_TYPESTATE(unconsumed);
};

class CONSUMABLE(unconsumed) DestructorTester {
public:
  DestructorTester();
  DestructorTester(int);
  
  void operator*() CALLABLE_WHEN("unconsumed");
  
  ~DestructorTester() CALLABLE_WHEN("consumed");
};

void baf0(const ConsumableClass<int>  var);
void baf1(const ConsumableClass<int> &var);
void baf2(const ConsumableClass<int> *var);

void baf3(ConsumableClass<int>   var);
void baf4(ConsumableClass<int>  &var);
void baf5(ConsumableClass<int>  *var);
void baf6(ConsumableClass<int> &&var);

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>();
}

ConsumableClass<int> returnsUnknown() RETURN_TYPESTATE(unknown);

void testInitialization() {
  ConsumableClass<int> var0;
  ConsumableClass<int> var1 = 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;
    *var1;
    
  } else {
    *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}}
  }
}

void testDestruction() {
  DestructorTester D0(42), D1(42), D2;
  
  *D0;
  *D1;
  *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}}
}

void testTempValue() {
  *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 {{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 {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}}
}

void testIfStmt() {
  ConsumableClass<int> var;
  
  if (var.isValid()) {
    *var;
  } else {
    *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
  }
  
  if (!var.isValid()) {
    *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
  } else {
    *var;
  }
  
  if (var) {
    // Empty
  } else {
    *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 {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
  }
  
  if (var == nullptr) {
    *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
  } else {
    // Empty
  }
}

void testComplexConditionals0() {
  ConsumableClass<int> var0, var1, var2;
  
  if (var0 && var1) {
    *var0;
    *var1;
    
  } 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;
    
  } 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;
    
  } 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; // 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;
    *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;
    *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;
    *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;
    *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;
    *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 '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
  // FIXME: Get this test to pass.
  if (var0 || var1 || var2) {
    *var0;
    *var1;
    *var2;
    
  } 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
}

void testComplexConditionals1() {
  ConsumableClass<int> var0, var1, var2;
  
  // Coerce all variables into the unknown state.
  baf4(var0);
  baf4(var1);
  baf4(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
}

void testStateChangeInBranch() {
  ConsumableClass<int> var;
  
  // Make var enter the 'unknown' state.
  baf4(var);
  
  if (!var) {
    var = ConsumableClass<int>(42);
  }
  
  *var;
}

void testFunctionParam(ConsumableClass<int> param) {
  
  if (param.isValid()) {
    *param;
  } else {
    *param;
  }
  
  param = nullptr;
  *param; // expected-warning {{invocation of method 'operator*' on object 'param' while it is in the 'consumed' state}}
}

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();
}

void testParamReturnTypestateCaller() {
  ConsumableClass<int> var;
  
  testParamReturnTypestateCallee(true, var);
  
  *var;
}

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'}}
}


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;
}

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;
}

void testCallingConventions() {
  ConsumableClass<int> var(42);
  
  baf0(var);  
  *var;
  
  baf1(var);  
  *var;
  
  baf2(&var);  
  *var;
  
  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(&var);  
  *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'unknown' state}}
  
  var = ConsumableClass<int>(42);
  baf6(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() {
  ConsumableClass<int> var;
  
  var = returnsUnconsumed();
  *var;
  
  var = returnsConsumed();
  *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;
  
  baf4(var);
  
  var.callableWhenUnknown();
}

void testMoveAsignmentish() {
  ConsumableClass<int>  var0;
  ConsumableClass<long> var1(42);
  
  *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 {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}}
  
  var1 = ConsumableClass<long>(42);
  var1 = nullptr;
  *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}}
}

void testConditionalMerge() {
  ConsumableClass<int> var;
  
  if (var.isValid()) {
    // Empty
  }
  
  *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
  
  if (var.isValid()) {
    // Empty
  } else {
    // Empty
  }
  
  *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
}

void testSetTypestate() {
  ConsumableClass<int> var(42);
  
  *var;
  
  var.consume();
  
  *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
  
  var.unconsume();
  
  *var;
}

void testConsumes0() {
  ConsumableClass<int> var(nullptr);
  
  *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
}

void testConsumes1() {
  ConsumableClass<int> var(42);
  
  var.unconsumedCall();
  var(6);
  
  var.unconsumedCall(); // expected-warning {{invalid invocation of method 'unconsumedCall' on object 'var' while it is in the 'consumed' state}}
}

void testUnreachableBlock() {
  ConsumableClass<int> var(42);
  
  if (var) {
    *var;
  } else {
    *var;
  }
  
  *var;
}


void testForLoop1() {
  ConsumableClass<int> var0, var1(42);
  
  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}}
  }
  
  *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}}
}

void testWhileLoop1() {
  int i = 10;
  
  ConsumableClass<int> var0, var1(42);
  
  while (i-- > 0) { // 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}}
  }
  
  *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}}
}

typedef const int*& IntegerPointerReference;
void testIsRValueRefishAndCanonicalType(IntegerPointerReference a) {}

namespace ContinueICETest {

bool cond1();
bool cond2();

static void foo1() {
  while (cond1()) {
    if (cond2())
      continue;
  }
}

static void foo2() {
  while (true) {
    if (false)
      continue;
  }
}

class runtime_error
{
public:
  virtual ~runtime_error();
};

void read(bool sf) {
    while (sf) {
        if(sf) throw runtime_error();
    }
}

} // end namespace ContinueICETest


namespace StatusUseCaseTests {

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);

  Status(const Status &other);
  Status(Status &&other);

  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; }

  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   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}}
}

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}}

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();
}

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() {
  Status s1 = doSomething();
  handleStatus(s1);

  Status s2 = doSomething();
  handleStatusRef(s2);

  Status s3 = doSomething();
  handleStatusPtr(&s3);

  Status s4 = doSomething();
  handleStatusUnmarked(s4);
}

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();
}

void testTemporariesWithConditionals2() {
  int a;
  
  Status s = doSomething();
  s.ignore();
  if (cond()) a = 0;
  else        a = 1;
}

void testTemporariesWithConditionals3() {
  Status s = doSomething();
  if (cond()) {
    s.check();
  }
}

void testTemporariesAndConstructors0() {
  Status s(doSomething());    // Test the copy constructor.
  s.check();
}

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();
}

void testTemporariesAndConstructors2F() {
  // Test the move constructor.
  Status s1 = doSomething();
  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 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();
}

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);
  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();
}

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


namespace std {
  void move();
  template<class T>
  void move(T&&);

  namespace __1 {
    void move();
    template<class T>
    void move(T&&);
  }
}

namespace PR18260 {
  class X {
    public:
      void move();
  } x;

  void test() {
    x.move();
    std::move();
    std::move(x);
    std::__1::move();
    std::__1::move(x);
  }
} // end namespace PR18260

@


1.1.1.4.4.1
log
@file warn-consumed-analysis.cpp was added on branch yamt-pagecache on 2014-05-22 16:19:41 +0000
@
text
@d1 901
@


1.1.1.4.4.2
log
@sync with head.

for a reference, the tree before this commit was tagged
as yamt-pagecache-tag8.

this commit was splitted into small chunks to avoid
a limitation of cvs.  ("Protocol error: too many arguments")
@
text
@a0 901
// RUN: %clang_cc1 -fsyntax-only -verify -Wconsumed -fcxx-exceptions -std=c++11 %s

// TODO: Switch to using macros for the expected warnings.

#define CALLABLE_WHEN(...)      __attribute__ ((callable_when(__VA_ARGS__)))
#define CONSUMABLE(state)       __attribute__ ((consumable(state)))
#define PARAM_TYPESTATE(state)  __attribute__ ((param_typestate(state)))
#define RETURN_TYPESTATE(state) __attribute__ ((return_typestate(state)))
#define SET_TYPESTATE(state)    __attribute__ ((set_typestate(state)))
#define TEST_TYPESTATE(state)   __attribute__ ((test_typestate(state)))

typedef decltype(nullptr) nullptr_t;

template <typename T>
class CONSUMABLE(unconsumed) ConsumableClass {
  T var;
  
public:
  ConsumableClass();
  ConsumableClass(nullptr_t p) RETURN_TYPESTATE(consumed);
  ConsumableClass(T val) RETURN_TYPESTATE(unconsumed);
  ConsumableClass(ConsumableClass<T> &other);
  ConsumableClass(ConsumableClass<T> &&other);
  
  ConsumableClass<T>& operator=(ConsumableClass<T>  &other);
  ConsumableClass<T>& operator=(ConsumableClass<T> &&other);
  ConsumableClass<T>& operator=(nullptr_t) SET_TYPESTATE(consumed);
  
  template <typename U>
  ConsumableClass<T>& operator=(ConsumableClass<U>  &other);
  
  template <typename U>
  ConsumableClass<T>& operator=(ConsumableClass<U> &&other);
  
  void operator()(int a) SET_TYPESTATE(consumed);
  void operator*() const CALLABLE_WHEN("unconsumed");
  void unconsumedCall() const CALLABLE_WHEN("unconsumed");
  void callableWhenUnknown() const CALLABLE_WHEN("unconsumed", "unknown");
  
  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);
  
  void constCall() const;
  void nonconstCall();
  
  void consume() SET_TYPESTATE(consumed);
  void unconsume() SET_TYPESTATE(unconsumed);
};

class CONSUMABLE(unconsumed) DestructorTester {
public:
  DestructorTester();
  DestructorTester(int);
  
  void operator*() CALLABLE_WHEN("unconsumed");
  
  ~DestructorTester() CALLABLE_WHEN("consumed");
};

void baf0(const ConsumableClass<int>  var);
void baf1(const ConsumableClass<int> &var);
void baf2(const ConsumableClass<int> *var);

void baf3(ConsumableClass<int>   var);
void baf4(ConsumableClass<int>  &var);
void baf5(ConsumableClass<int>  *var);
void baf6(ConsumableClass<int> &&var);

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>();
}

ConsumableClass<int> returnsUnknown() RETURN_TYPESTATE(unknown);

void testInitialization() {
  ConsumableClass<int> var0;
  ConsumableClass<int> var1 = 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;
    *var1;
    
  } else {
    *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}}
  }
}

void testDestruction() {
  DestructorTester D0(42), D1(42), D2;
  
  *D0;
  *D1;
  *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}}
}

void testTempValue() {
  *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 {{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 {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}}
}

void testIfStmt() {
  ConsumableClass<int> var;
  
  if (var.isValid()) {
    *var;
  } else {
    *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
  }
  
  if (!var.isValid()) {
    *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
  } else {
    *var;
  }
  
  if (var) {
    // Empty
  } else {
    *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 {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
  }
  
  if (var == nullptr) {
    *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
  } else {
    // Empty
  }
}

void testComplexConditionals0() {
  ConsumableClass<int> var0, var1, var2;
  
  if (var0 && var1) {
    *var0;
    *var1;
    
  } 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;
    
  } 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;
    
  } 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; // 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;
    *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;
    *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;
    *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;
    *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;
    *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 '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
  // FIXME: Get this test to pass.
  if (var0 || var1 || var2) {
    *var0;
    *var1;
    *var2;
    
  } 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
}

void testComplexConditionals1() {
  ConsumableClass<int> var0, var1, var2;
  
  // Coerce all variables into the unknown state.
  baf4(var0);
  baf4(var1);
  baf4(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
}

void testStateChangeInBranch() {
  ConsumableClass<int> var;
  
  // Make var enter the 'unknown' state.
  baf4(var);
  
  if (!var) {
    var = ConsumableClass<int>(42);
  }
  
  *var;
}

void testFunctionParam(ConsumableClass<int> param) {
  
  if (param.isValid()) {
    *param;
  } else {
    *param;
  }
  
  param = nullptr;
  *param; // expected-warning {{invocation of method 'operator*' on object 'param' while it is in the 'consumed' state}}
}

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();
}

void testParamReturnTypestateCaller() {
  ConsumableClass<int> var;
  
  testParamReturnTypestateCallee(true, var);
  
  *var;
}

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'}}
}


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;
}

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;
}

void testCallingConventions() {
  ConsumableClass<int> var(42);
  
  baf0(var);  
  *var;
  
  baf1(var);  
  *var;
  
  baf2(&var);  
  *var;
  
  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(&var);  
  *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'unknown' state}}
  
  var = ConsumableClass<int>(42);
  baf6(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() {
  ConsumableClass<int> var;
  
  var = returnsUnconsumed();
  *var;
  
  var = returnsConsumed();
  *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;
  
  baf4(var);
  
  var.callableWhenUnknown();
}

void testMoveAsignmentish() {
  ConsumableClass<int>  var0;
  ConsumableClass<long> var1(42);
  
  *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 {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}}
  
  var1 = ConsumableClass<long>(42);
  var1 = nullptr;
  *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}}
}

void testConditionalMerge() {
  ConsumableClass<int> var;
  
  if (var.isValid()) {
    // Empty
  }
  
  *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
  
  if (var.isValid()) {
    // Empty
  } else {
    // Empty
  }
  
  *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
}

void testSetTypestate() {
  ConsumableClass<int> var(42);
  
  *var;
  
  var.consume();
  
  *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
  
  var.unconsume();
  
  *var;
}

void testConsumes0() {
  ConsumableClass<int> var(nullptr);
  
  *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
}

void testConsumes1() {
  ConsumableClass<int> var(42);
  
  var.unconsumedCall();
  var(6);
  
  var.unconsumedCall(); // expected-warning {{invalid invocation of method 'unconsumedCall' on object 'var' while it is in the 'consumed' state}}
}

void testUnreachableBlock() {
  ConsumableClass<int> var(42);
  
  if (var) {
    *var;
  } else {
    *var;
  }
  
  *var;
}


void testForLoop1() {
  ConsumableClass<int> var0, var1(42);
  
  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}}
  }
  
  *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}}
}

void testWhileLoop1() {
  int i = 10;
  
  ConsumableClass<int> var0, var1(42);
  
  while (i-- > 0) { // 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}}
  }
  
  *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}}
}

typedef const int*& IntegerPointerReference;
void testIsRValueRefishAndCanonicalType(IntegerPointerReference a) {}

namespace ContinueICETest {

bool cond1();
bool cond2();

static void foo1() {
  while (cond1()) {
    if (cond2())
      continue;
  }
}

static void foo2() {
  while (true) {
    if (false)
      continue;
  }
}

class runtime_error
{
public:
  virtual ~runtime_error();
};

void read(bool sf) {
    while (sf) {
        if(sf) throw runtime_error();
    }
}

} // end namespace ContinueICETest


namespace StatusUseCaseTests {

class CONSUMABLE(unconsumed)
      __attribute__((consumable_auto_cast_state))
      __attribute__((consumable_set_state_on_read))
    Status {
  int code;

public:
  Status() RETURN_TYPESTATE(consumed);
  Status(int c) RETURN_TYPESTATE(unconsumed);

  Status(const Status &other);
  Status(Status &&other);

  Status& operator=(const Status &other) CALLABLE_WHEN("unknown", "consumed");
  Status& operator=(Status &&other) CALLABLE_WHEN("unknown", "consumed");

  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");
};


bool   cond();
Status doSomething();
void   handleStatus(const Status& s RETURN_TYPESTATE(consumed));
void   handleStatusRef(Status& s);
void   handleStatusPtr(Status* s);
void   handleStatusUnmarked(const Status& s);

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}}

Status testSimpleTemporariesReturn0() {
  return doSomething();
}

Status testSimpleTemporariesReturn1() {
  Status s = doSomething();
  return s;
}

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() {
  Status s1 = doSomething();
  handleStatus(s1);

  Status s2 = doSomething();
  handleStatusRef(s2);

  Status s3 = doSomething();
  handleStatusPtr(&s3);

  Status s4 = doSomething();
  handleStatusUnmarked(s4);
}

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();
}

void testTemporariesWithConditionals2() {
  int a;
  
  Status s = doSomething();
  s.ignore();
  if (cond()) a = 0;
  else        a = 1;
}

void testTemporariesWithConditionals3() {
  Status s = doSomething();
  if (cond()) {
    s.check();
  }
}

void testTemporariesAndConstructors0() {
  Status s(doSomething());    // Test the copy constructor.
  s.check();
}

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();
}

void testTemporariesAndConstructors2F() {
  // Test the move constructor.
  Status s1 = doSomething();
  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 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();
}

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);
  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();
}

Status testReturnAutocast() {
  Status s = doSomething();
  s.check();  // consume s
  return s;   // should autocast back to unconsumed
}

} // end namespace InitializerAssertionFailTest


namespace std {
  void move();
  template<class T>
  void move(T&&);

  namespace __1 {
    void move();
    template<class T>
    void move(T&&);
  }
}

namespace PR18260 {
  class X {
    public:
      void move();
  } x;

  void test() {
    x.move();
    std::move();
    std::move(x);
    std::__1::move();
    std::__1::move(x);
  }
} // end namespace PR18260
@


