Refactor the check for bad divide into a checker.
Also fix a checker context bug: the Dst set is not always empty initially.
Because in GRExprEngine::CheckerVisit(), *CurrSet is used repeatedly.
So we removed the Dst.empty() condition in ~CheckerContext() when deciding
whether to do autotransision.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@80786 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp
index a6b580b..a36916b 100644
--- a/lib/Analysis/GRExprEngine.cpp
+++ b/lib/Analysis/GRExprEngine.cpp
@@ -2700,44 +2700,6 @@
// Transfer functions: Binary operators.
//===----------------------------------------------------------------------===//
-const GRState* GRExprEngine::CheckDivideZero(Expr* Ex, const GRState* state,
- ExplodedNode* Pred, SVal Denom) {
-
- // Divide by undefined? (potentially zero)
-
- if (Denom.isUndef()) {
- ExplodedNode* DivUndef = Builder->generateNode(Ex, state, Pred);
-
- if (DivUndef) {
- DivUndef->markAsSink();
- ExplicitBadDivides.insert(DivUndef);
- }
-
- return 0;
- }
-
- // Check for divide/remainder-by-zero.
- // First, "assume" that the denominator is 0 or undefined.
- const GRState* zeroState = state->assume(Denom, false);
-
- // Second, "assume" that the denominator cannot be 0.
- state = state->assume(Denom, true);
-
- // Create the node for the divide-by-zero (if it occurred).
- if (zeroState)
- if (ExplodedNode* DivZeroNode = Builder->generateNode(Ex, zeroState, Pred)) {
- DivZeroNode->markAsSink();
-
- if (state)
- ImplicitBadDivides.insert(DivZeroNode);
- else
- ExplicitBadDivides.insert(DivZeroNode);
-
- }
-
- return state;
-}
-
void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
ExplodedNode* Pred,
ExplodedNodeSet& Dst) {
@@ -2765,10 +2727,14 @@
ExplodedNodeSet Tmp2;
Visit(RHS, *I1, Tmp2);
+
+ ExplodedNodeSet CheckedSet;
+ CheckerVisit(B, CheckedSet, Tmp2, true);
// With both the LHS and RHS evaluated, process the operation itself.
- for (ExplodedNodeSet::iterator I2=Tmp2.begin(), E2=Tmp2.end(); I2 != E2; ++I2) {
+ for (ExplodedNodeSet::iterator I2=CheckedSet.begin(), E2=CheckedSet.end();
+ I2 != E2; ++I2) {
const GRState* state = GetState(*I2);
const GRState* OldSt = state;
@@ -2799,17 +2765,6 @@
continue;
}
- case BinaryOperator::Div:
- case BinaryOperator::Rem:
-
- // Special checking for integer denominators.
- if (RHS->getType()->isIntegerType() &&
- RHS->getType()->isScalarType()) {
-
- state = CheckDivideZero(B, state, *I2, RightV);
- if (!state) continue;
- }
-
// FALL-THROUGH.
default: {
@@ -2875,24 +2830,12 @@
SVal location = state->getSVal(LHS);
EvalLoad(Tmp3, LHS, *I2, state, location);
- for (ExplodedNodeSet::iterator I3=Tmp3.begin(), E3=Tmp3.end(); I3!=E3; ++I3) {
+ for (ExplodedNodeSet::iterator I3=Tmp3.begin(), E3=Tmp3.end(); I3!=E3;
+ ++I3) {
state = GetState(*I3);
SVal V = state->getSVal(LHS);
- // Check for divide-by-zero.
- if ((Op == BinaryOperator::Div || Op == BinaryOperator::Rem)
- && RHS->getType()->isIntegerType()
- && RHS->getType()->isScalarType()) {
-
- // CheckDivideZero returns a new state where the denominator
- // is assumed to be non-zero.
- state = CheckDivideZero(B, state, *I3, RightV);
-
- if (!state)
- continue;
- }
-
// Propagate undefined values (left-side).
if (V.isUndef()) {
EvalStore(Dst, B, LHS, *I3, state->BindExpr(B, V),