forked from OSchip/llvm-project
[Consumed] Treat by-value class arguments as consuming by default, like rvalue refs.
Differential Revision: https://reviews.llvm.org/D67743 llvm-svn: 372361
This commit is contained in:
parent
ccf8d5b829
commit
9dd57df26a
clang
|
@ -644,10 +644,10 @@ bool ConsumedStmtVisitor::handleCall(const CallExpr *Call, const Expr *ObjArg,
|
|||
continue;
|
||||
|
||||
// Adjust state on the caller side.
|
||||
if (isRValueRef(ParamType))
|
||||
setStateForVarOrTmp(StateMap, PInfo, consumed::CS_Consumed);
|
||||
else if (ReturnTypestateAttr *RT = Param->getAttr<ReturnTypestateAttr>())
|
||||
if (ReturnTypestateAttr *RT = Param->getAttr<ReturnTypestateAttr>())
|
||||
setStateForVarOrTmp(StateMap, PInfo, mapReturnTypestateAttrState(RT));
|
||||
else if (isRValueRef(ParamType) || isConsumableType(ParamType))
|
||||
setStateForVarOrTmp(StateMap, PInfo, consumed::CS_Consumed);
|
||||
else if (isPointerOrRef(ParamType) &&
|
||||
(!ParamType->getPointeeType().isConstQualified() ||
|
||||
isSetOnReadPtrType(ParamType)))
|
||||
|
|
|
@ -53,12 +53,18 @@ class CONSUMABLE(unconsumed) DestructorTester {
|
|||
public:
|
||||
DestructorTester();
|
||||
DestructorTester(int);
|
||||
DestructorTester(nullptr_t) RETURN_TYPESTATE(unconsumed);
|
||||
DestructorTester(DestructorTester &&);
|
||||
|
||||
void operator*() CALLABLE_WHEN("unconsumed");
|
||||
|
||||
~DestructorTester() CALLABLE_WHEN("consumed");
|
||||
|
||||
};
|
||||
|
||||
void dtByVal(DestructorTester);
|
||||
void dtByValMarkUnconsumed(DestructorTester RETURN_TYPESTATE(unconsumed));
|
||||
|
||||
void baf0(const ConsumableClass<int> var);
|
||||
void baf1(const ConsumableClass<int> &var);
|
||||
void baf2(const ConsumableClass<int> *var);
|
||||
|
@ -120,6 +126,19 @@ void testDestruction() {
|
|||
expected-warning {{invalid invocation of method '~DestructorTester' on object 'D1' while it is in the 'unconsumed' state}}
|
||||
}
|
||||
|
||||
void testDestructionByVal() {
|
||||
{
|
||||
// both the var and the temporary are consumed:
|
||||
DestructorTester D0(nullptr);
|
||||
dtByVal((DestructorTester &&)D0);
|
||||
}
|
||||
{
|
||||
// the var is consumed but the temporary isn't:
|
||||
DestructorTester D1(nullptr);
|
||||
dtByValMarkUnconsumed((DestructorTester &&)D1); // expected-warning {{invalid invocation of method '~DestructorTester' on a temporary object while it is in the 'unconsumed' state}}
|
||||
}
|
||||
}
|
||||
|
||||
void testTempValue() {
|
||||
*ConsumableClass<int>(); // expected-warning {{invalid invocation of method 'operator*' on a temporary object while it is in the 'consumed' state}}
|
||||
}
|
||||
|
@ -413,10 +432,15 @@ void testParamReturnTypestateCallee(bool cond, ConsumableClass<int> &Param RETUR
|
|||
Param.consume();
|
||||
}
|
||||
|
||||
void testRvalueRefParamReturnTypestateCallee(ConsumableClass<int> &&Param RETURN_TYPESTATE(unconsumed)) {
|
||||
Param.unconsume();
|
||||
}
|
||||
|
||||
void testParamReturnTypestateCaller() {
|
||||
ConsumableClass<int> var;
|
||||
|
||||
testParamReturnTypestateCallee(true, var);
|
||||
testRvalueRefParamReturnTypestateCallee((ConsumableClass<int> &&)var);
|
||||
|
||||
*var;
|
||||
}
|
||||
|
@ -480,6 +504,9 @@ void testCallingConventions() {
|
|||
|
||||
baf2(&var);
|
||||
*var;
|
||||
|
||||
baf3(var);
|
||||
*var;
|
||||
|
||||
baf4(var);
|
||||
*var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'unknown' state}}
|
||||
|
|
Loading…
Reference in New Issue