Skip to content

Commit

Permalink
[Consumed] Treat by-value class arguments as consuming by default, li…
Browse files Browse the repository at this point in the history
…ke rvalue refs.

Differential Revision: https://reviews.llvm.org/D67743

llvm-svn: 372361
  • Loading branch information
comex committed Sep 19, 2019
1 parent ccf8d5b commit 9dd57df
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 3 deletions.
6 changes: 3 additions & 3 deletions clang/lib/Analysis/Consumed.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)))
Expand Down
27 changes: 27 additions & 0 deletions clang/test/SemaCXX/warn-consumed-analysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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}}
}
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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}}
Expand Down

0 comments on commit 9dd57df

Please sign in to comment.