aboutsummaryrefslogtreecommitdiff
path: root/lib/Analysis/GRExprEngine.cpp
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2009-12-09 02:45:41 +0000
committerTed Kremenek <kremenek@apple.com>2009-12-09 02:45:41 +0000
commit17f4da8f150f6b9dfb571cebd6299b06948e5385 (patch)
tree24dd1a4b4798c09225ce137fad517540f3bcae77 /lib/Analysis/GRExprEngine.cpp
parent13d555859cd643d657000401ebc88ca404d23bba (diff)
Fix a horrid bug in GRExprEngine::CheckerVisit() that was identified
by the test case in PR 5627. Essentially we shouldn't clear the ExplodedNodeSet where we deposit newly constructed nodes if that set is the 'Dst' set passed in. It is not okay to clear that set because it may already contain nodes. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@90931 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/GRExprEngine.cpp')
-rw-r--r--lib/Analysis/GRExprEngine.cpp99
1 files changed, 58 insertions, 41 deletions
diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp
index c9c419beaa..6104781007 100644
--- a/lib/Analysis/GRExprEngine.cpp
+++ b/lib/Analysis/GRExprEngine.cpp
@@ -120,7 +120,7 @@ void GRExprEngine::CheckerVisit(Stmt *S, ExplodedNodeSet &Dst,
ExplodedNodeSet &Src, bool isPrevisit) {
if (Checkers.empty()) {
- Dst = Src;
+ Dst.insert(Src);
return;
}
@@ -128,10 +128,13 @@ void GRExprEngine::CheckerVisit(Stmt *S, ExplodedNodeSet &Dst,
ExplodedNodeSet *PrevSet = &Src;
for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end(); I!=E;++I){
- ExplodedNodeSet *CurrSet = (I+1 == E) ? &Dst
- : (PrevSet == &Tmp) ? &Src : &Tmp;
-
- CurrSet->clear();
+ ExplodedNodeSet *CurrSet = 0;
+ if (I+1 == E)
+ CurrSet = &Dst;
+ else {
+ CurrSet = (PrevSet == &Tmp) ? &Src : &Tmp;
+ CurrSet->clear();
+ }
void *tag = I->first;
Checker *checker = I->second;
@@ -187,7 +190,7 @@ void GRExprEngine::CheckerVisitBind(const Stmt *AssignE, const Stmt *StoreE,
SVal location, SVal val, bool isPrevisit) {
if (Checkers.empty()) {
- Dst = Src;
+ Dst.insert(Src);
return;
}
@@ -196,10 +199,14 @@ void GRExprEngine::CheckerVisitBind(const Stmt *AssignE, const Stmt *StoreE,
for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end(); I!=E; ++I)
{
- ExplodedNodeSet *CurrSet = (I+1 == E) ? &Dst
- : (PrevSet == &Tmp) ? &Src : &Tmp;
+ ExplodedNodeSet *CurrSet = 0;
+ if (I+1 == E)
+ CurrSet = &Dst;
+ else {
+ CurrSet = (PrevSet == &Tmp) ? &Src : &Tmp;
+ CurrSet->clear();
+ }
- CurrSet->clear();
void *tag = I->first;
Checker *checker = I->second;
@@ -395,10 +402,14 @@ void GRExprEngine::ProcessStmt(Stmt* S, GRStmtNodeBuilder& builder) {
ExplodedNodeSet *SrcSet = &Tmp2;
for (CheckersOrdered::iterator I = Checkers.begin(), E = Checkers.end();
I != E; ++I) {
- ExplodedNodeSet *DstSet = (I+1 == E) ? &Tmp
- : (SrcSet == &Tmp2) ? &Tmp3
- : &Tmp2;
- DstSet->clear();
+ ExplodedNodeSet *DstSet = 0;
+ if (I+1 == E)
+ DstSet = &Tmp;
+ else {
+ DstSet = (SrcSet == &Tmp2) ? &Tmp3 : &Tmp2;
+ DstSet->clear();
+ }
+
void *tag = I->first;
Checker *checker = I->second;
for (ExplodedNodeSet::iterator NI = SrcSet->begin(), NE = SrcSet->end();
@@ -1391,10 +1402,14 @@ void GRExprEngine::EvalLocation(ExplodedNodeSet &Dst, Stmt *S,
for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end(); I!=E; ++I)
{
- ExplodedNodeSet *CurrSet = (I+1 == E) ? &Dst
- : (PrevSet == &Tmp) ? &Src : &Tmp;
+ ExplodedNodeSet *CurrSet = 0;
+ if (I+1 == E)
+ CurrSet = &Dst;
+ else {
+ CurrSet = (PrevSet == &Tmp) ? &Src : &Tmp;
+ CurrSet->clear();
+ }
- CurrSet->clear();
void *tag = I->first;
Checker *checker = I->second;
@@ -1658,6 +1673,8 @@ void GRExprEngine::VisitCallRec(CallExpr* CE, ExplodedNode* Pred,
}
// Finally, evaluate the function call.
+ ExplodedNodeSet DstTmp3;
+
for (ExplodedNodeSet::iterator DI = DstTmp.begin(), DE = DstTmp.end();
DI != DE; ++DI) {
@@ -1666,40 +1683,40 @@ void GRExprEngine::VisitCallRec(CallExpr* CE, ExplodedNode* Pred,
// FIXME: Add support for symbolic function calls (calls involving
// function pointer values that are symbolic).
-
- // Check for the "noreturn" attribute.
-
SaveAndRestore<bool> OldSink(Builder->BuildSinks);
-
- ExplodedNodeSet DstTmp3, DstChecker, DstOther;
+ ExplodedNodeSet DstChecker;
// If the callee is processed by a checker, skip the rest logic.
if (CheckerEvalCall(CE, DstChecker, *DI))
DstTmp3 = DstChecker;
else {
- // Dispatch to the plug-in transfer function.
- SaveOr OldHasGen(Builder->HasGeneratedNode);
- Pred = *DI;
-
- // Dispatch to transfer function logic to handle the call itself.
- // FIXME: Allow us to chain together transfer functions.
- assert(Builder && "GRStmtNodeBuilder must be defined.");
+ for (ExplodedNodeSet::iterator DI_Checker = DstChecker.begin(),
+ DE_Checker = DstChecker.end();
+ DI_Checker != DE_Checker; ++DI_Checker) {
+
+ // Dispatch to the plug-in transfer function.
+ unsigned OldSize = DstTmp3.size();
+ SaveOr OldHasGen(Builder->HasGeneratedNode);
+ Pred = *DI_Checker;
+
+ // Dispatch to transfer function logic to handle the call itself.
+ // FIXME: Allow us to chain together transfer functions.
+ assert(Builder && "GRStmtNodeBuilder must be defined.");
- if (!EvalOSAtomic(DstOther, *this, *Builder, CE, L, Pred))
- getTF().EvalCall(DstOther, *this, *Builder, CE, L, Pred);
-
- // Handle the case where no nodes where generated. Auto-generate that
- // contains the updated state if we aren't generating sinks.
- if (!Builder->BuildSinks && DstTmp3.empty() &&
- !Builder->HasGeneratedNode)
- MakeNode(DstOther, CE, Pred, state);
-
- DstTmp3 = DstOther;
+ if (!EvalOSAtomic(DstTmp3, *this, *Builder, CE, L, Pred))
+ getTF().EvalCall(DstTmp3, *this, *Builder, CE, L, Pred);
+
+ // Handle the case where no nodes where generated. Auto-generate that
+ // contains the updated state if we aren't generating sinks.
+ if (!Builder->BuildSinks && DstTmp3.size() == OldSize &&
+ !Builder->HasGeneratedNode)
+ MakeNode(DstTmp3, CE, Pred, state);
+ }
}
-
- // Perform the post-condition check of the CallExpr.
- CheckerVisit(CE, Dst, DstTmp3, false);
}
+
+ // Perform the post-condition check of the CallExpr.
+ CheckerVisit(CE, Dst, DstTmp3, false);
}
//===----------------------------------------------------------------------===//