From: Manuel Klimek Date: Thu, 8 May 2014 11:50:00 +0000 (+0000) Subject: Explicitly keep track of temporaries during the consumed analysis. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f439181e7c49fce6f220ef66f5bbb82d4af7f5d8;p=clang Explicitly keep track of temporaries during the consumed analysis. This makes the consumed analysis less dependent on the CFG layout and fixes a bug where we wouldn't warn on an unconsumed value. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@208300 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Analysis/Analyses/Consumed.h b/include/clang/Analysis/Analyses/Consumed.h index 3c9ba78548..36e07c2190 100644 --- a/include/clang/Analysis/Analyses/Consumed.h +++ b/include/clang/Analysis/Analyses/Consumed.h @@ -185,8 +185,8 @@ namespace consumed { /// \brief Set the consumed state of a given temporary value. void setState(const CXXBindTemporaryExpr *Tmp, ConsumedState State); - /// \brief Remove the variable from our state map. - void remove(const VarDecl *Var); + /// \brief Remove the temporary value from our state map. + void remove(const CXXBindTemporaryExpr *Tmp); /// \brief Tests to see if there is a mismatch in the states stored in two /// maps. diff --git a/lib/Analysis/Consumed.cpp b/lib/Analysis/Consumed.cpp index 6d590ab2e3..e3dcb92378 100644 --- a/lib/Analysis/Consumed.cpp +++ b/lib/Analysis/Consumed.cpp @@ -1233,8 +1233,8 @@ void ConsumedStateMap::setState(const CXXBindTemporaryExpr *Tmp, TmpMap[Tmp] = State; } -void ConsumedStateMap::remove(const VarDecl *Var) { - VarMap.erase(Var); +void ConsumedStateMap::remove(const CXXBindTemporaryExpr *Tmp) { + TmpMap.erase(Tmp); } bool ConsumedStateMap::operator!=(const ConsumedStateMap *Other) const { @@ -1413,6 +1413,7 @@ void ConsumedAnalyzer::run(AnalysisDeclContext &AC) { Visitor.checkCallability(PropagationInfo(BTE), DTor.getDestructorDecl(AC.getASTContext()), BTE->getExprLoc()); + CurrStates->remove(BTE); break; } @@ -1432,8 +1433,6 @@ void ConsumedAnalyzer::run(AnalysisDeclContext &AC) { } } - CurrStates->clearTemporaries(); - // TODO: Handle other forms of branching with precision, including while- // and for-loops. (Deferred) if (!splitState(CurrBlock, Visitor)) { diff --git a/test/SemaCXX/warn-consumed-analysis.cpp b/test/SemaCXX/warn-consumed-analysis.cpp index bd091c6f1c..977b862a92 100644 --- a/test/SemaCXX/warn-consumed-analysis.cpp +++ b/test/SemaCXX/warn-consumed-analysis.cpp @@ -704,6 +704,8 @@ public: void clear() CALLABLE_WHEN("unknown", "consumed") SET_TYPESTATE(consumed); ~Status() CALLABLE_WHEN("unknown", "consumed"); + + operator bool() const; // Will not consume the object. }; @@ -735,6 +737,10 @@ 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(); }