]> granicus.if.org Git - clang/commitdiff
Refined divide-by-zero checking to distinguish between must and may
authorTed Kremenek <kremenek@apple.com>
Fri, 7 Mar 2008 19:04:53 +0000 (19:04 +0000)
committerTed Kremenek <kremenek@apple.com>
Fri, 7 Mar 2008 19:04:53 +0000 (19:04 +0000)
divide-by-zero errors.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@48013 91177308-0d34-0410-b5e6-96231b3b80d8

Analysis/GRExprEngine.cpp
Analysis/GRSimpleVals.cpp
include/clang/Analysis/PathSensitive/GRExprEngine.h

index 3b4b787d6a69b907d8c6bd62d5cb96ec9515d4f7..082e124765a2e789ed390caf489ff10802a3523e 100644 (file)
@@ -1040,7 +1040,7 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
             
             if (DivUndef) {
               DivUndef->markAsSink();
-              BadDivides.insert(DivUndef);
+              ExplicitBadDivides.insert(DivUndef);
             }
             
             continue;
@@ -1050,21 +1050,28 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
           //
           // First, "assume" that the denominator is 0 or undefined.
           
-          bool isFeasible = false;
-          ValueState* ZeroSt =  Assume(St, RightV, false, isFeasible);
+          bool isFeasibleZero = false;
+          ValueState* ZeroSt =  Assume(St, RightV, false, isFeasibleZero);
           
-          if (isFeasible)
+          // Second, "assume" that the denominator cannot be 0.
+          
+          bool isFeasibleNotZero = false;
+          St = Assume(St, RightV, true, isFeasibleNotZero);
+          
+          // Create the node for the divide-by-zero (if it occurred).
+          
+          if (isFeasibleZero)
             if (NodeTy* DivZeroNode = Builder->generateNode(B, ZeroSt, N2)) {
               DivZeroNode->markAsSink();
-              BadDivides.insert(DivZeroNode);
+              
+              if (isFeasibleNotZero)
+                ImplicitBadDivides.insert(DivZeroNode);
+              else
+                ExplicitBadDivides.insert(DivZeroNode);
+
             }
           
-          // Second, "assume" that the denominator cannot be 0.
-          
-          isFeasible = false;
-          St = Assume(St, RightV, true, isFeasible);
-          
-          if (!isFeasible)
+          if (!isFeasibleNotZero)
             continue;
         }
         
@@ -1208,7 +1215,7 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
               
               if (DivUndef) {
                 DivUndef->markAsSink();
-                BadDivides.insert(DivUndef);
+                ExplicitBadDivides.insert(DivUndef);
               }
               
               continue;
@@ -1216,24 +1223,30 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
 
             // First, "assume" that the denominator is 0.
             
-            bool isFeasible = false;
-            ValueState* ZeroSt = Assume(St, RightV, false, isFeasible);
+            bool isFeasibleZero = false;
+            ValueState* ZeroSt = Assume(St, RightV, false, isFeasibleZero);
             
-            if (isFeasible) {
+            // Second, "assume" that the denominator cannot be 0.
+            
+            bool isFeasibleNotZero = false;
+            St = Assume(St, RightV, true, isFeasibleNotZero);
+            
+            // Create the node for the divide-by-zero error (if it occurred).
+            
+            if (isFeasibleZero) {
               NodeTy* DivZeroNode = Builder->generateNode(B, ZeroSt, N2);
               
               if (DivZeroNode) {
                 DivZeroNode->markAsSink();
-                BadDivides.insert(DivZeroNode);
+                
+                if (isFeasibleNotZero)
+                  ImplicitBadDivides.insert(DivZeroNode);
+                else
+                  ExplicitBadDivides.insert(DivZeroNode);
               }
             }
             
-            // Second, "assume" that the denominator cannot be 0.
-            
-            isFeasible = false;
-            St = Assume(St, RightV, true, isFeasible);
-            
-            if (!isFeasible)
+            if (!isFeasibleNotZero)
               continue;
             
             // Fall-through.  The logic below processes the divide.
@@ -1659,7 +1672,8 @@ struct VISIBILITY_HIDDEN DOTGraphTraits<GRExprEngine::NodeTy*> :
         GraphPrintCheckerState->isUndefDeref(N) ||
         GraphPrintCheckerState->isUndefStore(N) ||
         GraphPrintCheckerState->isUndefControlFlow(N) ||
-        GraphPrintCheckerState->isBadDivide(N) ||
+        GraphPrintCheckerState->isExplicitBadDivide(N) ||
+        GraphPrintCheckerState->isImplicitBadDivide(N) ||
         GraphPrintCheckerState->isUndefResult(N) ||
         GraphPrintCheckerState->isBadCall(N) ||
         GraphPrintCheckerState->isUndefArg(N))
@@ -1702,8 +1716,10 @@ struct VISIBILITY_HIDDEN DOTGraphTraits<GRExprEngine::NodeTy*> :
           Out << "\\|Dereference of undefialied value.\\l";
         else if (GraphPrintCheckerState->isUndefStore(N))
           Out << "\\|Store to Undefined LVal.";
-        else if (GraphPrintCheckerState->isBadDivide(N))
-          Out << "\\|Divide-by zero or undefined value.";
+        else if (GraphPrintCheckerState->isExplicitBadDivide(N))
+          Out << "\\|Explicit divide-by zero or undefined value.";
+        else if (GraphPrintCheckerState->isImplicitBadDivide(N))
+          Out << "\\|Implicit divide-by zero or undefined value.";
         else if (GraphPrintCheckerState->isUndefResult(N))
           Out << "\\|Result of operation is undefined.";
         else if (GraphPrintCheckerState->isNoReturnCall(N))
index af8ea2f4bbb08a8edc9b141e0eca731985483d74..95cf3bbbe40c47c9b5a11b8115733b928e0ec236 100644 (file)
@@ -121,8 +121,8 @@ unsigned RunGRSimpleVals(CFG& cfg, FunctionDecl& FD, ASTContext& Ctx,
               "Dereference of undefined value.");
   
   EmitWarning(Diag, SrcMgr,
-              CheckerState->bad_divides_begin(),
-              CheckerState->bad_divides_end(),
+              CheckerState->explicit_bad_divides_begin(),
+              CheckerState->explicit_bad_divides_end(),
               "Division by zero/undefined value.");
   
   EmitWarning(Diag, SrcMgr,
index 6a7d243add5176524cdf39812b091c6402a46cbf..cd8d555886ae3003b8b0478483b0c2331d03eaee 100644 (file)
@@ -98,9 +98,15 @@ protected:
   ///  taking a dereference on an undefined value.
   BadDerefTy UndefDeref;
 
-  /// BadDivides - Nodes in the ExplodedGraph that result from evaluating
-  ///  a divide-by-zero or divide-by-undefined.
-  BadDividesTy BadDivides;
+  /// ImplicitBadDivides - Nodes in the ExplodedGraph that result from 
+  ///  evaluating a divide or modulo operation where the denominator
+  ///  MAY be zero.
+  BadDividesTy ImplicitBadDivides;
+  
+  /// ExplicitBadDivides - Nodes in the ExplodedGraph that result from 
+  ///  evaluating a divide or modulo operation where the denominator
+  ///  MUST be zero or undefined.
+  BadDividesTy ExplicitBadDivides;
   
   /// UndefResults - Nodes in the ExplodedGraph where the operands are defined
   ///  by the result is not.  Excludes divide-by-zero errors.
@@ -169,8 +175,12 @@ public:
     return N->isSink() && UndefDeref.count(const_cast<NodeTy*>(N)) != 0;
   }
   
-  bool isBadDivide(const NodeTy* N) const {
-    return N->isSink() && BadDivides.count(const_cast<NodeTy*>(N)) != 0; 
+  bool isImplicitBadDivide(const NodeTy* N) const {
+    return N->isSink() && ImplicitBadDivides.count(const_cast<NodeTy*>(N)) != 0; 
+  }
+  
+  bool isExplicitBadDivide(const NodeTy* N) const {
+    return N->isSink() && ExplicitBadDivides.count(const_cast<NodeTy*>(N)) != 0; 
   }
   
   bool isNoReturnCall(const NodeTy* N) const {
@@ -199,8 +209,22 @@ public:
   undef_deref_iterator undef_derefs_end() { return UndefDeref.end(); }
   
   typedef BadDividesTy::iterator bad_divide_iterator;
-  bad_divide_iterator bad_divides_begin() { return BadDivides.begin(); }
-  bad_divide_iterator bad_divides_end() { return BadDivides.end(); }
+
+  bad_divide_iterator explicit_bad_divides_begin() {
+    return ExplicitBadDivides.begin();
+  }
+  
+  bad_divide_iterator explicit_bad_divides_end() {
+    return ExplicitBadDivides.end();
+  }
+  
+  bad_divide_iterator implicit_bad_divides_begin() {
+    return ImplicitBadDivides.begin();
+  }
+  
+  bad_divide_iterator implicit_bad_divides_end() {
+    return ImplicitBadDivides.end();
+  }
   
   typedef UndefResultsTy::iterator undef_result_iterator;
   undef_result_iterator undef_results_begin() { return UndefResults.begin(); }