summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorManuel Klimek <klimek@google.com>2014-05-08 11:50:00 +0000
committerManuel Klimek <klimek@google.com>2014-05-08 11:50:00 +0000
commitb33bded1762064cf690f69bee3dbb5a94d634dd2 (patch)
treecad21f328ba2462726b2815cfda402a5d51e55a3
parent49ff754d4be5d8eb84f71eb2d97156901d4290cd (diff)
downloadbcm5719-llvm-b33bded1762064cf690f69bee3dbb5a94d634dd2.tar.gz
bcm5719-llvm-b33bded1762064cf690f69bee3dbb5a94d634dd2.zip
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. llvm-svn: 208300
-rw-r--r--clang/include/clang/Analysis/Analyses/Consumed.h4
-rw-r--r--clang/lib/Analysis/Consumed.cpp7
-rw-r--r--clang/test/SemaCXX/warn-consumed-analysis.cpp6
3 files changed, 11 insertions, 6 deletions
diff --git a/clang/include/clang/Analysis/Analyses/Consumed.h b/clang/include/clang/Analysis/Analyses/Consumed.h
index 3c9ba78548b..36e07c21907 100644
--- a/clang/include/clang/Analysis/Analyses/Consumed.h
+++ b/clang/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/clang/lib/Analysis/Consumed.cpp b/clang/lib/Analysis/Consumed.cpp
index 6d590ab2e3d..e3dcb923786 100644
--- a/clang/lib/Analysis/Consumed.cpp
+++ b/clang/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/clang/test/SemaCXX/warn-consumed-analysis.cpp b/clang/test/SemaCXX/warn-consumed-analysis.cpp
index bd091c6f1cc..977b862a92b 100644
--- a/clang/test/SemaCXX/warn-consumed-analysis.cpp
+++ b/clang/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();
}
OpenPOWER on IntegriCloud