Use a temporary destination set such that we can clear fake auto transitions.
Otherwise, even when real evaluation occurs, the previous fake auto
transitions would still be in the destination set, causing fake state
bifurcation.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@90967 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp
index daa249f..a31b573 100644
--- a/lib/Analysis/GRExprEngine.cpp
+++ b/lib/Analysis/GRExprEngine.cpp
@@ -152,13 +152,26 @@
ExplodedNodeSet &Dst,
const GRState *state,
ExplodedNode *Pred) {
+ bool Evaluated = false;
+ ExplodedNodeSet DstTmp;
+
for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end();I!=E;++I) {
void *tag = I->first;
Checker *checker = I->second;
- if (checker->GR_EvalNilReceiver(Dst, *Builder, *this, ME, Pred, state, tag))
+ if (checker->GR_EvalNilReceiver(DstTmp, *Builder, *this, ME, Pred, state,
+ tag)) {
+ Evaluated = true;
break;
+ } else
+ // The checker didn't evaluate the expr. Restore the Dst.
+ DstTmp.clear();
}
+
+ if (Evaluated)
+ Dst.insert(DstTmp);
+ else
+ Dst.insert(Pred);
}
// CheckerEvalCall returns true if one of the checkers processed the node.
@@ -168,17 +181,25 @@
ExplodedNodeSet &Dst,
ExplodedNode *Pred) {
bool Evaluated = false;
+ ExplodedNodeSet DstTmp;
for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end();I!=E;++I) {
void *tag = I->first;
Checker *checker = I->second;
- if (checker->GR_EvalCallExpr(Dst, *Builder, *this, CE, Pred, tag)) {
+ if (checker->GR_EvalCallExpr(DstTmp, *Builder, *this, CE, Pred, tag)) {
Evaluated = true;
break;
- }
+ } else
+ // The checker didn't evaluate the expr. Restore the DstTmp set.
+ DstTmp.clear();
}
+ if (Evaluated)
+ Dst.insert(DstTmp);
+ else
+ Dst.insert(Pred);
+
return Evaluated;
}