llvm_unreachable("invalid enum");
}
+static bool isRValueRefish(QualType ParamType) {
+ return ParamType->isRValueReferenceType() ||
+ (ParamType->isLValueReferenceType() &&
+ !cast<LValueReferenceType>(*ParamType).isSpelledAsLValue());
+}
+
static bool isTestingFunction(const FunctionDecl *FunDecl) {
return FunDecl->hasAttr<TestsTypestateAttr>();
}
+static bool isValueType(QualType ParamType) {
+ return !(ParamType->isPointerType() || ParamType->isReferenceType());
+}
+
static ConsumedState mapConsumableAttrState(const QualType QT) {
assert(isConsumableType(QT));
// Adjust state on the caller side.
- if (ParamType->isRValueReferenceType() ||
- (ParamType->isLValueReferenceType() &&
- !cast<LValueReferenceType>(*ParamType).isSpelledAsLValue())) {
-
+ if (isRValueRefish(ParamType)) {
StateMap->setState(PInfo.getVar(), consumed::CS_Consumed);
} else if (Param->hasAttr<ReturnTypestateAttr>()) {
StateMap->setState(PInfo.getVar(),
mapReturnTypestateAttrState(Param->getAttr<ReturnTypestateAttr>()));
- } else if (!(ParamType.isConstQualified() ||
- ((ParamType->isReferenceType() ||
- ParamType->isPointerType()) &&
- ParamType->getPointeeType().isConstQualified()))) {
+ } else if (!isValueType(ParamType) &&
+ !ParamType->getPointeeType().isConstQualified()) {
StateMap->setState(PInfo.getVar(), consumed::CS_Unknown);
}
ConsumedState ParamState = consumed::CS_None;
if (Param->hasAttr<ParamTypestateAttr>()) {
- ParamState =
- mapParamTypestateAttrState(Param->getAttr<ParamTypestateAttr>());
-
- } else if (!(ParamType->isPointerType() || ParamType->isReferenceType()) &&
- isConsumableType(ParamType)) {
+ const ParamTypestateAttr *PTAttr = Param->getAttr<ParamTypestateAttr>();
+ ParamState = mapParamTypestateAttrState(PTAttr);
+ } else if (isValueType(ParamType) && isConsumableType(ParamType)) {
ParamState = mapConsumableAttrState(ParamType);
+ } else if (isRValueRefish(ParamType) &&
+ isConsumableType(ParamType->getPointeeType())) {
+
+ ParamState = mapConsumableAttrState(ParamType->getPointeeType());
+
} else if (ParamType->isReferenceType() &&
isConsumableType(ParamType->getPointeeType())) {
ParamState = consumed::CS_Unknown;
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 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> var0, var1, var2;
// Coerce all variables into the unknown state.
- baf3(var0);
- baf3(var1);
- baf3(var2);
+ baf4(var0);
+ baf4(var1);
+ baf4(var2);
if (var0 && var1) {
*var0;
ConsumableClass<int> var;
// Make var enter the 'unknown' state.
- baf3(var);
+ baf4(var);
if (!var) {
var = ConsumableClass<int>(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);
baf2(&var);
*var;
- baf3(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);
- baf4(&var);
+ baf5(&var);
*var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'unknown' state}}
var = ConsumableClass<int>(42);
- baf5(static_cast<ConsumableClass<int>&&>(var));
+ baf6(static_cast<ConsumableClass<int>&&>(var));
*var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
}
*var;
- baf3(var);
+ baf4(var);
var.callableWhenUnknown();
}