From: DeLesley Hutchins Date: Fri, 18 Oct 2013 18:36:21 +0000 (+0000) Subject: Consumed analysis: All the return_typestate parameter to be attached to the X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c5cdafcdb8eea9625e86b015ba7a2504f18a99b7;p=clang Consumed analysis: All the return_typestate parameter to be attached to the default constructor. Patch by chris.wailes@gmail.com, reviewed by delesley. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@192991 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Analysis/Consumed.cpp b/lib/Analysis/Consumed.cpp index a7d747f705..ef9617a3ec 100644 --- a/lib/Analysis/Consumed.cpp +++ b/lib/Analysis/Consumed.cpp @@ -660,38 +660,46 @@ void ConsumedStmtVisitor::VisitCXXConstructExpr(const CXXConstructExpr *Call) { ASTContext &CurrContext = AC.getASTContext(); QualType ThisType = Constructor->getThisType(CurrContext)->getPointeeType(); - if (isConsumableType(ThisType)) { - if (Constructor->isDefaultConstructor()) { + if (!isConsumableType(ThisType)) + return; + + // FIXME: What should happen if someone annotates the move constructor? + if (Constructor->hasAttr()) { + ReturnTypestateAttr *RTAttr = Constructor->getAttr(); + ConsumedState RetState = mapReturnTypestateAttrState(RTAttr); + PropagationMap.insert(PairType(Call, PropagationInfo(RetState, ThisType))); + + } else if (Constructor->isDefaultConstructor()) { + + PropagationMap.insert(PairType(Call, + PropagationInfo(consumed::CS_Consumed, ThisType))); + + } else if (Constructor->isMoveConstructor()) { + + PropagationInfo PInfo = + PropagationMap.find(Call->getArg(0))->second; + + if (PInfo.isVar()) { + const VarDecl* Var = PInfo.getVar(); PropagationMap.insert(PairType(Call, - PropagationInfo(consumed::CS_Consumed, ThisType))); + PropagationInfo(StateMap->getState(Var), ThisType))); - } else if (Constructor->isMoveConstructor()) { - - PropagationInfo PInfo = - PropagationMap.find(Call->getArg(0))->second; - - if (PInfo.isVar()) { - const VarDecl* Var = PInfo.getVar(); - - PropagationMap.insert(PairType(Call, - PropagationInfo(StateMap->getState(Var), ThisType))); - - StateMap->setState(Var, consumed::CS_Consumed); - - } else { - PropagationMap.insert(PairType(Call, PInfo)); - } - - } else if (Constructor->isCopyConstructor()) { - MapType::iterator Entry = PropagationMap.find(Call->getArg(0)); - - if (Entry != PropagationMap.end()) - PropagationMap.insert(PairType(Call, Entry->second)); + StateMap->setState(Var, consumed::CS_Consumed); } else { - propagateReturnType(Call, Constructor, ThisType); + PropagationMap.insert(PairType(Call, PInfo)); } + + } else if (Constructor->isCopyConstructor()) { + MapType::iterator Entry = PropagationMap.find(Call->getArg(0)); + + if (Entry != PropagationMap.end()) + PropagationMap.insert(PairType(Call, Entry->second)); + + } else { + ConsumedState RetState = mapConsumableAttrState(ThisType); + PropagationMap.insert(PairType(Call, PropagationInfo(RetState, ThisType))); } } diff --git a/test/SemaCXX/warn-consumed-analysis.cpp b/test/SemaCXX/warn-consumed-analysis.cpp index 2e45216cfe..b84c69c453 100644 --- a/test/SemaCXX/warn-consumed-analysis.cpp +++ b/test/SemaCXX/warn-consumed-analysis.cpp @@ -51,9 +51,10 @@ public: class CONSUMABLE(unconsumed) DestructorTester { public: + DestructorTester() RETURN_TYPESTATE(unconsumed); DestructorTester(int); - void operator*(); + void operator*() CALLABLE_WHEN("unconsumed"); ~DestructorTester() CALLABLE_WHEN("consumed"); }; @@ -101,9 +102,14 @@ void testDestruction() { *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}} + 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() {