]> granicus.if.org Git - clang/commitdiff
Added lazy "symbolication" of parameter variables and global variables.
authorTed Kremenek <kremenek@apple.com>
Tue, 26 Feb 2008 02:15:56 +0000 (02:15 +0000)
committerTed Kremenek <kremenek@apple.com>
Tue, 26 Feb 2008 02:15:56 +0000 (02:15 +0000)
Added recording of divide-by-zero and divide-by-uninitialized nodes.

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

Analysis/GRExprEngine.cpp
Analysis/RValues.cpp
Analysis/SymbolManager.cpp
Analysis/ValueState.cpp
include/clang/Analysis/PathSensitive/GRExprEngine.h
include/clang/Analysis/PathSensitive/RValues.h
include/clang/Analysis/PathSensitive/SymbolManager.h

index 6c363b00b3e4ace581b714e6047d0dd9bd236cd9..fcbe4ccaefa3a121b7f419d8b60f9d6250b535bd 100644 (file)
@@ -396,6 +396,22 @@ void GRExprEngine::Nodify(NodeSet& Dst, Stmt* S, NodeTy* Pred,
 
 void GRExprEngine::VisitDeclRefExpr(DeclRefExpr* D, NodeTy* Pred, NodeSet& Dst){
 
+  if (VarDecl* VD = dyn_cast<VarDecl>(D->getDecl()))
+    if (VD->hasGlobalStorage() || isa<ParmVarDecl>(VD)) {
+
+      StateTy StOld = Pred->getState();
+      StateTy St = Symbolicate(StOld, VD);
+
+      if (!(St == StOld)) {
+        if (D != CurrentStmt)
+          Nodify(Dst, D, Pred, St);
+        else
+          Nodify(Dst, D, Pred, SetRVal(St, D, GetRVal(St, D)));
+        
+        return;
+      }
+    }
+  
   if (D != CurrentStmt) {
     Dst.Add(Pred); // No-op. Simply propagate the current state unchanged.
     return;
@@ -796,7 +812,20 @@ void GRExprEngine::VisitLVal(Expr* Ex, NodeTy* Pred, NodeSet& Dst) {
   
   Ex = Ex->IgnoreParens();
   
-  if (isa<DeclRefExpr>(Ex)) {
+  if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(Ex)) {
+    
+    if (VarDecl* VD = dyn_cast<VarDecl>(DR->getDecl()))
+      if (VD->hasGlobalStorage() || isa<ParmVarDecl>(VD)) {
+        
+        StateTy StOld = Pred->getState();
+        StateTy St = Symbolicate(StOld, VD);
+        
+        if (!(St == StOld)) {
+          Nodify(Dst, Ex, Pred, St);
+          return;
+        }
+      }
+    
     Dst.Add(Pred);
     return;
   }
@@ -857,20 +886,33 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
       
       if ((Op == BinaryOperator::Div || Op == BinaryOperator::Rem)
           && RHS->getType()->isIntegerType()) {
+
+        // Check if the denominator is uninitialized.
         
-        // Check for divide/remaindner-by-zero.
-        
-        // First, "assume" that the denominator is 0.
+        if (RightV.isUninit()) {
+          NodeTy* DivUninit = Builder->generateNode(B, St, N2);
+          
+          if (DivUninit) {
+            DivUninit->markAsSink();
+            BadDivides.insert(DivUninit);
+          }
+          
+          continue;
+        }
+          
+        // Check for divide/remainder-by-zero.
+        //
+        // First, "assume" that the denominator is 0 or uninitialized.
         
         bool isFeasible = false;
-        StateTy ZeroSt = Assume(St, RightV, false, isFeasible);
+        StateTy ZeroSt =  Assume(St, RightV, false,isFeasible);
         
         if (isFeasible) {
           NodeTy* DivZeroNode = Builder->generateNode(B, ZeroSt, N2);
           
           if (DivZeroNode) {
             DivZeroNode->markAsSink();
-            DivZeroes.insert(DivZeroNode);
+            BadDivides.insert(DivZeroNode);
           }
         }
         
@@ -1003,8 +1045,19 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
           if ((Op == BinaryOperator::Div || Op == BinaryOperator::Rem)
               && RHS->getType()->isIntegerType()) {
             
-             // Check for divide/remainder-by-zero.
-                        
+            // Check if the denominator is uninitialized.
+                
+            if (RightV.isUninit()) {
+              NodeTy* DivUninit = Builder->generateNode(B, St, N2);
+              
+              if (DivUninit) {
+                DivUninit->markAsSink();
+                BadDivides.insert(DivUninit);
+              }
+              
+              continue;
+            }
+            
             // First, "assume" that the denominator is 0.
             
             bool isFeasible = false;
@@ -1015,7 +1068,7 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
               
               if (DivZeroNode) {
                 DivZeroNode->markAsSink();
-                DivZeroes.insert(DivZeroNode);
+                BadDivides.insert(DivZeroNode);
               }
             }
             
index 178d794065d5fff53f970c98bbb83d23e6a1201a..bc6a75c7f7fbb5c2ab7feac53c17ae2027f300eb 100644 (file)
@@ -214,7 +214,7 @@ NonLVal NonLVal::MakeIntTruthVal(ValueManager& ValMgr, bool b) {
   return nonlval::ConcreteInt(ValMgr.getTruthValue(b));
 }
 
-RVal RVal::GetSymbolValue(SymbolManager& SymMgr, ParmVarDecl* D) {
+RVal RVal::GetSymbolValue(SymbolManager& SymMgr, VarDecl* D) {
 
   QualType T = D->getType();
   
index ced5741f447d8b569fa5107f2f611d9d6d09f0a9..dd71dc9d04d1d05974f5e71294cc8e57b98fe122 100644 (file)
 
 using namespace clang;
 
-SymbolID SymbolManager::getSymbol(ParmVarDecl* D) {
+SymbolID SymbolManager::getSymbol(VarDecl* D) {
+
+  assert (isa<ParmVarDecl>(D) || D->hasGlobalStorage());
+  
   SymbolID& X = DataToSymbol[getKey(D)];
   
   if (!X.isInitialized()) {
     X = SymbolToData.size();
-    SymbolToData.push_back(SymbolDataParmVar(D));
+    
+    if (ParmVarDecl* VD = dyn_cast<ParmVarDecl>(D))
+      SymbolToData.push_back(SymbolDataParmVar(VD));
+    else
+      SymbolToData.push_back(SymbolDataGlobalVar(D));
   }
   
   return X;
-}
-
+}  
 SymbolID SymbolManager::getContentsOfSymbol(SymbolID sym) {
   SymbolID& X = DataToSymbol[getKey(sym)];
   
@@ -45,6 +52,9 @@ QualType SymbolData::getType(const SymbolManager& SymMgr) const {
       
     case ParmKind:
       return cast<SymbolDataParmVar>(this)->getDecl()->getType();
+
+    case GlobalKind:
+      return cast<SymbolDataGlobalVar>(this)->getDecl()->getType();
       
     case ContentsOfKind: {
       SymbolID x = cast<SymbolDataContentsOf>(this)->getSymbol();
index 75f719ae6a193dc4419c7fcf803ec2931401cc08..03b2996b650fc01fd3ed1de3c3c9172626a5ea63 100644 (file)
@@ -78,8 +78,16 @@ ValueStateManager::RemoveDeadBindings(ValueState St, Stmt* Loc,
   // Iterate over the variable bindings.
 
   for (ValueState::vb_iterator I = St.vb_begin(), E = St.vb_end(); I!=E ; ++I)
-    if (Liveness.isLive(Loc, I.getKey()))
+    if (Liveness.isLive(Loc, I.getKey())) {
       WList.push_back(I.getKey());
+      
+      RVal X = I.getData();
+      
+      for (RVal::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end(); 
+           SI != SE; ++SI) {        
+        MarkedSymbols.insert(*SI);
+      }
+    }
 
   // Perform the mark-and-sweep.
 
index bc8bec78e1a11b24511bf140cc6d6ee7d01a00e0..a2d92f1ea6545a8d34c76cf2e2a5e10997e5109a 100644 (file)
@@ -135,9 +135,9 @@ protected:
   ///  taking a dereference on an uninitialized value.
   BadDerefTy UninitDeref;
 
-  /// DivZeroes - Nodes in the ExplodedGraph that result from evaluating
-  ///  a divide-by-zero.
-  DivZerosTy DivZeroes;
+  /// BadDivides - Nodes in the ExplodedGraph that result from evaluating
+  ///  a divide-by-zero or divide-by-uninitialized.
+  DivZerosTy BadDivides;
   
   bool StateCleaned;
   
@@ -172,20 +172,7 @@ public:
   
   /// getInitialState - Return the initial state used for the root vertex
   ///  in the ExplodedGraph.
-  StateTy getInitialState() {
-    StateTy St = StateMgr.getInitialState();
-    
-    // Iterate the parameters.
-    FunctionDecl& F = G.getFunctionDecl();
-    
-    for (FunctionDecl::param_iterator I = F.param_begin(), E = F.param_end(); 
-                                                           I != E; ++I) {      
-      St = SetRVal(St, lval::DeclVal(*I),
-                   RVal::GetSymbolValue(SymMgr, *I));
-    }
-    
-    return St;
-  }
+  StateTy getInitialState() { return StateMgr.getInitialState(); }
   
   bool isUninitControlFlow(const NodeTy* N) const {
     return N->isSink() && UninitBranches.count(const_cast<NodeTy*>(N)) != 0;
@@ -207,6 +194,10 @@ public:
     return N->isSink() && UninitDeref.count(const_cast<NodeTy*>(N)) != 0;
   }
   
+  bool isBadDivide(const NodeTy* N) const {
+    return N->isSink() && BadDivides.count(const_cast<NodeTy*>(N)) != 0; 
+  }
+  
   typedef BadDerefTy::iterator null_iterator;
   null_iterator null_begin() { return ExplicitNullDeref.begin(); }
   null_iterator null_end() { return ExplicitNullDeref.end(); }
@@ -271,6 +262,15 @@ public:
     return StateMgr.GetLVal(St, Ex);
   }
   
+  StateTy Symbolicate(StateTy St, VarDecl* VD) {
+    lval::DeclVal X(VD);
+    
+    if (GetRVal(St, X).isUnknown()) {
+      return SetRVal(St, lval::DeclVal(VD), RVal::GetSymbolValue(SymMgr, VD));
+    }
+    else return St;
+  }
+  
   inline NonLVal MakeConstantVal(uint64_t X, Expr* Ex) {
     return NonLVal::MakeVal(ValMgr, X, Ex->getType(), Ex->getLocStart());
   }
index f6403949c03181b5dcb3e21ea23885399cf0f3f7..e43edb9253aa3526ee70eecfddaac9547f37bd5a 100644 (file)
@@ -65,7 +65,7 @@ public:
     return !(*this == R);
   }
   
-  static RVal GetSymbolValue(SymbolManager& SymMgr, ParmVarDecl *D);
+  static RVal GetSymbolValue(SymbolManager& SymMgr, VarDecl *D);
   
   inline bool isUnknown() const {
     return getRawKind() == UnknownKind;
index d29e0e08b9c57b0090ba114e797215c68345e90e..3747f54d7d9c5c62602cbf9cff47b6f96cd162e2 100644 (file)
@@ -49,7 +49,7 @@ public:
 
 class SymbolData {
 public:
-  enum Kind { UninitKind, ParmKind, ContentsOfKind };
+  enum Kind { UninitKind, ParmKind, GlobalKind, ContentsOfKind };
   
 private:
   uintptr_t Data;
@@ -95,6 +95,18 @@ public:
     return D->getKind() == ParmKind;
   }
 };
+  
+class SymbolDataGlobalVar : public SymbolData {
+public:
+  SymbolDataGlobalVar(VarDecl* VD) : SymbolData(VD, GlobalKind) {}
+  
+  VarDecl* getDecl() const { return (VarDecl*) getPtr(); }
+  
+  // Implement isa<T> support.
+  static inline bool classof(const SymbolData* D) {
+    return D->getKind() == GlobalKind;
+  }
+};
 
 class SymbolDataContentsOf : public SymbolData {
 public:
@@ -157,7 +169,7 @@ public:
   SymbolManager();
   ~SymbolManager();
   
-  SymbolID getSymbol(ParmVarDecl* D);
+  SymbolID getSymbol(VarDecl* D);
   SymbolID getContentsOfSymbol(SymbolID sym);
   
   inline const SymbolData& getSymbolData(SymbolID ID) const {