diff options
author | Ted Kremenek <kremenek@apple.com> | 2008-10-20 23:40:25 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2008-10-20 23:40:25 +0000 |
commit | c13b6e251afb9530bbcc8c6f26dc4266f4f0c93b (patch) | |
tree | feefe490f34bf709a18e08aefe758f5135173666 | |
parent | 9253b0f3d70b49f216e86447494ec0ff2315b31a (diff) |
Further improve path-sensitivity with divide-by-zero checking by assuming that a denominator cannot be zero even when the result of an '/' or '%' expression is unknown.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@57855 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Analysis/GRExprEngine.cpp | 49 | ||||
-rw-r--r-- | test/Analysis/misc-ps.m | 14 |
2 files changed, 45 insertions, 18 deletions
diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp index 94fbf35b1b..32c83669e3 100644 --- a/lib/Analysis/GRExprEngine.cpp +++ b/lib/Analysis/GRExprEngine.cpp @@ -1989,8 +1989,8 @@ void GRExprEngine::VisitReturnStmt(ReturnStmt* S, NodeTy* Pred, NodeSet& Dst) { // Transfer functions: Binary operators. //===----------------------------------------------------------------------===// -bool GRExprEngine::CheckDivideZero(Expr* Ex, const GRState* St, - NodeTy* Pred, SVal Denom) { +const GRState* GRExprEngine::CheckDivideZero(Expr* Ex, const GRState* St, + NodeTy* Pred, SVal Denom) { // Divide by undefined? (potentially zero) @@ -2002,7 +2002,7 @@ bool GRExprEngine::CheckDivideZero(Expr* Ex, const GRState* St, ExplicitBadDivides.insert(DivUndef); } - return true; + return 0; } // Check for divide/remainder-by-zero. @@ -2029,7 +2029,7 @@ bool GRExprEngine::CheckDivideZero(Expr* Ex, const GRState* St, } - return !isFeasibleNotZero; + return isFeasibleNotZero ? St : 0; } void GRExprEngine::VisitBinaryOperator(BinaryOperator* B, @@ -2059,6 +2059,8 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B, for (NodeSet::iterator I2=Tmp2.begin(), E2=Tmp2.end(); I2 != E2; ++I2) { const GRState* St = GetState(*I2); + const GRState* OldSt = St; + SVal RightV = GetSVal(St, RHS); BinaryOperator::Opcode Op = B->getOpcode(); @@ -2089,11 +2091,11 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B, case BinaryOperator::Div: case BinaryOperator::Rem: - // Special checking for integer denominators. - - if (RHS->getType()->isIntegerType() - && CheckDivideZero(B, St, *I2, RightV)) - continue; + // Special checking for integer denominators. + if (RHS->getType()->isIntegerType()) { + St = CheckDivideZero(B, St, *I2, RightV); + if (!St) continue; + } // FALL-THROUGH. @@ -2108,7 +2110,13 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B, SVal Result = EvalBinOp(Op, LeftV, RightV); if (Result.isUnknown()) { - Dst.Add(*I2); + if (OldSt != St) { + // Generate a new node if we have already created a new state. + MakeNode(Dst, B, *I2, St); + } + else + Dst.Add(*I2); + continue; } @@ -2150,6 +2158,18 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B, St = GetState(*I3); SVal V = GetSVal(St, LHS); + // Check for divide-by-zero. + if ((Op == BinaryOperator::Div || Op == BinaryOperator::Rem) + && RHS->getType()->isIntegerType()) { + + // CheckDivideZero returns a new state where the denominator + // is assumed to be non-zero. + St = CheckDivideZero(B, St, *I3, RightV); + + if (!St) + continue; + } + // Propagate undefined values (left-side). if (V.isUndef()) { EvalStore(Dst, B, LHS, *I3, SetSVal(St, B, V), location, V); @@ -2176,14 +2196,7 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B, RightV = EvalCast(RightV, CTy); // Evaluate operands and promote to result type. - - if ((Op == BinaryOperator::Div || Op == BinaryOperator::Rem) - && RHS->getType()->isIntegerType()) { - - if (CheckDivideZero(B, St, *I3, RightV)) - continue; - } - else if (RightV.isUndef()) { + if (RightV.isUndef()) { // Propagate undefined values (right-side). EvalStore(Dst, B, LHS, *I3, SetSVal(St, B, RightV), location, RightV); continue; diff --git a/test/Analysis/misc-ps.m b/test/Analysis/misc-ps.m index 956d0dfb59..f473f290c7 100644 --- a/test/Analysis/misc-ps.m +++ b/test/Analysis/misc-ps.m @@ -29,3 +29,17 @@ void r6268365() { if (x == 0) x = x / j; // no-warning } +void divzeroassume(unsigned x, unsigned j) { + x /= j; + if (j == 0) x /= 0; // no-warning + if (j == 0) x /= j; // no-warning + if (j == 0) x = x / 0; // no-warning +} + +void divzeroassumeB(unsigned x, unsigned j) { + x = x / j; + if (j == 0) x /= 0; // no-warning + if (j == 0) x /= j; // no-warning + if (j == 0) x = x / 0; // no-warning +} + |