]> granicus.if.org Git - clang/commitdiff
Simplified transfer function logic for ++/-- operators.
authorTed Kremenek <kremenek@apple.com>
Fri, 15 Feb 2008 22:09:30 +0000 (22:09 +0000)
committerTed Kremenek <kremenek@apple.com>
Fri, 15 Feb 2008 22:09:30 +0000 (22:09 +0000)
Added more boilerplate transfer function support for pointer arithmetic.
Added more pretty-printing support for symbolic constraints.
Added transfer function support for handling enum values.
Minor pointer types cleanup in ExplodedGraphImpl.

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

Analysis/ExplodedGraph.cpp
Analysis/GRExprEngine.cpp
Analysis/RValues.cpp
Analysis/ValueState.cpp
include/clang/Analysis/PathSensitive/ExplodedGraph.h
include/clang/Analysis/PathSensitive/GRExprEngine.h
include/clang/Analysis/PathSensitive/GRTransferFuncs.h
include/clang/Analysis/PathSensitive/RValues.h

index 826162f243839991554a822764228cce5f307cca..ca5842656f7398c713f04f1b5dda3ad8eb3dcf21 100644 (file)
@@ -75,8 +75,7 @@ ExplodedGraphImpl::~ExplodedGraphImpl() {
   // of the FoldingSets are nodes allocated from the BumpPtrAllocator,
   // so all of those will get nuked when that object is destroyed.
   for (EdgeNodeSetMap::iterator I=Nodes.begin(), E=Nodes.end(); I!=E; ++I) {
-    llvm::FoldingSet<ExplodedNodeImpl>* ENodes = 
-      reinterpret_cast<llvm::FoldingSet<ExplodedNodeImpl>*>(I->second);
+    llvm::FoldingSet<ExplodedNodeImpl>* ENodes = I->second;
     
     for (llvm::FoldingSet<ExplodedNodeImpl>::iterator
          I=ENodes->begin(), E=ENodes->end(); I!=E; ++I)
index 5702198b381e53f840838134572c990096907468..3cd490e330b78ee9699b1cb6ae874a2eafbf4e50 100644 (file)
@@ -387,8 +387,7 @@ void GRExprEngine::VisitDeclRefExpr(DeclRefExpr* D, NodeTy* Pred, NodeSet& Dst){
   
   StateTy St = Pred->getState();
   
-  Nodify(Dst, D, Pred,
-         SetValue(St, D, GetValue(St, lval::DeclVal(D->getDecl()))));
+  Nodify(Dst, D, Pred, SetValue(St, D, GetValue(St, D)));
 }
 
 void GRExprEngine::VisitCast(Expr* CastE, Expr* E, NodeTy* Pred, NodeSet& Dst) {
@@ -485,51 +484,29 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U,
     NodeTy* N1 = *I1;
     StateTy St = N1->getState();
     
-    switch (U->getOpcode()) {
-      case UnaryOperator::PostInc: {
-        const LValue& L1 = GetLValue(St, U->getSubExpr());
-        NonLValue R1 = cast<NonLValue>(GetValue(St, L1));
-        
-        NonLValue Result = EvalBinaryOp(ValMgr, BinaryOperator::Add,
-                                        R1, GetRValueConstant(1U, U));
-        
-        Nodify(Dst, U, N1, SetValue(SetValue(St, U, R1), L1, Result));
-        break;
-      }
-        
-      case UnaryOperator::PostDec: {
-        const LValue& L1 = GetLValue(St, U->getSubExpr());
-        NonLValue R1 = cast<NonLValue>(GetValue(St, L1));
-        
-        NonLValue Result = EvalBinaryOp(ValMgr, BinaryOperator::Sub,
-                                        R1, GetRValueConstant(1U, U));
-        
+    // Handle ++ and -- (both pre- and post-increment).
+    
+    if (U->isIncrementDecrementOp()) {
+      const LValue& L1 = GetLValue(St, U->getSubExpr());
+      RValue R1 = GetValue(St, L1);
+      
+      BinaryOperator::Opcode Op = U->isIncrementOp() ? BinaryOperator::Add
+                                                     : BinaryOperator::Sub;
+      
+      RValue Result = EvalBinaryOp(ValMgr, Op, R1, GetRValueConstant(1U, U));
+      
+      if (U->isPostfix())
         Nodify(Dst, U, N1, SetValue(SetValue(St, U, R1), L1, Result));
-        break;
-      }
-        
-      case UnaryOperator::PreInc: {
-        const LValue& L1 = GetLValue(St, U->getSubExpr());
-        NonLValue R1 = cast<NonLValue>(GetValue(St, L1));
-        
-        NonLValue Result = EvalBinaryOp(ValMgr, BinaryOperator::Add,
-                                        R1, GetRValueConstant(1U, U));
-        
+      else
         Nodify(Dst, U, N1, SetValue(SetValue(St, U, Result), L1, Result));
-        break;
-      }
-        
-      case UnaryOperator::PreDec: {
-        const LValue& L1 = GetLValue(St, U->getSubExpr());
-        NonLValue R1 = cast<NonLValue>(GetValue(St, L1));
         
-        NonLValue Result = EvalBinaryOp(ValMgr, BinaryOperator::Sub,
-                                        R1, GetRValueConstant(1U, U));
+      continue;
+    }    
+    
+    // Handle all other unary operators.
+    
+    switch (U->getOpcode()) {
 
-        Nodify(Dst, U, N1, SetValue(SetValue(St, U, Result), L1, Result));
-        break;
-      }
-        
       case UnaryOperator::Minus: {
         const NonLValue& R1 = cast<NonLValue>(GetValue(St, U->getSubExpr()));
         Nodify(Dst, U, N1, SetValue(St, U, EvalMinus(ValMgr, U, R1)));
@@ -703,28 +680,7 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
           continue;
         }
         
-        if (isa<LValue>(V1)) {
-          // FIXME: Add support for RHS being a non-lvalue.
-          const LValue& L1 = cast<LValue>(V1);
-          
-          if (isa<LValue>(V2)) {          
-            const LValue& L2 = cast<LValue>(V2);
-            Nodify(Dst, B, N2, SetValue(St, B,
-                                        EvalBinaryOp(ValMgr, Op, L1, L2)));
-          }
-          else {
-            const NonLValue& R2 = cast<NonLValue>(V2);
-            Nodify(Dst, B, N2, SetValue(St, B,
-                                        EvalBinaryOp(ValMgr, Op, L1, R2)));
-          }
-        }
-        else {
-          const NonLValue& R1 = cast<NonLValue>(V1);
-          const NonLValue& R2 = cast<NonLValue>(V2);
-            
-          Nodify(Dst, B, N2, SetValue(St, B, EvalBinaryOp(ValMgr, Op, R1, R2)));
-        }
-        
+        Nodify(Dst, B, N2, SetValue(St, B, EvalBinaryOp(ValMgr, Op, V1, V2)));
         continue;
       
       }
@@ -746,14 +702,17 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
           if (Op >= BinaryOperator::AndAssign)
             ((int&) Op) -= (BinaryOperator::AndAssign - BinaryOperator::And);
           else
-            ((int&) Op) -= BinaryOperator::MulAssign;
+            ((int&) Op) -= BinaryOperator::MulAssign;          
           
-          if (isa<LValue>(V2)) {
-            // FIXME: Add support for Non-LValues on RHS.
+          if (B->getType()->isPointerType()) { // Perform pointer arithmetic.
+            const NonLValue& R2 = cast<NonLValue>(V2);
+            Result = EvalBinaryOp(ValMgr, Op, L1, R2);
+          }
+          else if (isa<LValue>(V2)) {          // LValue comparison.
             const LValue& L2 = cast<LValue>(V2);
             Result = EvalBinaryOp(ValMgr, Op, L1, L2);
           }
-          else {
+          else { // Any operation between two Non-LValues.
             const NonLValue& R1 = cast<NonLValue>(GetValue(N1->getState(), L1));
             const NonLValue& R2 = cast<NonLValue>(V2);
             Result = EvalBinaryOp(ValMgr, Op, R1, R2);
index 8eb607c9e5338bdc55f702878ff5f41519711c4a..a9b44eb3d2a9f8c4f6234a5f31266b452a23c823 100644 (file)
@@ -428,11 +428,23 @@ void RValue::print(std::ostream& Out) const {
 }
 
 static void printOpcode(std::ostream& Out, BinaryOperator::Opcode Op) {
-  switch (Op) {      
+  switch (Op) {
+    case BinaryOperator::Mul: Out << "*"; break;
+    case BinaryOperator::Div: Out << "/"; break;
+    case BinaryOperator::Rem: Out << "%" ; break;
     case BinaryOperator::Add: Out << "+" ; break;
     case BinaryOperator::Sub: Out << "-" ; break;
+    case BinaryOperator::Shl: Out << "<<" ; break;
+    case BinaryOperator::Shr: Out << ">>" ; break;
+    case BinaryOperator::LT: Out << "<" ; break;
+    case BinaryOperator::GT: Out << ">" ; break;
+    case BinaryOperator::LE: Out << "<=" ; break;
+    case BinaryOperator::GE: Out << ">=" ; break;    
     case BinaryOperator::EQ: Out << "=="; break;
     case BinaryOperator::NE: Out << "!="; break;
+    case BinaryOperator::And: Out << "&" ; break;
+    case BinaryOperator::Xor: Out << "^" ; break;
+    case BinaryOperator::Or: Out << "|" ; break;      
     default: assert(false && "Not yet implemented.");
   }        
 }
index 27818efa343029f22f3f2da471da0a0ba55d73de..9b2ed9686a9c720d0435c3d1f1288d799aebe28d 100644 (file)
@@ -91,7 +91,8 @@ ValueStateManager::RemoveDeadBindings(ValueState St, Stmt* Loc,
     Marked.insert(V);
     
     if (V->getType()->isPointerType()) {
-      const LValue& LV = cast<LValue>(GetValue(St, lval::DeclVal(V)));      
+      const LValue& LV =
+        cast<LValue>(GetValue(St, lval::DeclVal(cast<VarDecl>(V))));      
       
       for (RValue::symbol_iterator SI=LV.symbol_begin(), SE=LV.symbol_end();
            SI != SE; ++SI)
@@ -205,8 +206,25 @@ RValue ValueStateManager::GetValue(ValueState St, Expr* E, bool* hasVal) {
         // context we assume that we are retrieving the value contained
         // within the referenced variables.
         
-      case Stmt::DeclRefExprClass:
-        return GetValue(St, lval::DeclVal(cast<DeclRefExpr>(E)->getDecl()));
+      case Stmt::DeclRefExprClass: {
+        ValueDecl* D = cast<DeclRefExpr>(E)->getDecl();
+        
+        if (VarDecl* VD = dyn_cast<VarDecl>(D))
+          return GetValue(St, lval::DeclVal(VD));
+        else if (EnumConstantDecl* ED = dyn_cast<EnumConstantDecl>(D)) {
+          // FIXME: Do we need to cache a copy of this enum, since it
+          // already has persistent storage?  We do this because we
+          // are comparing states using pointer equality.  Perhaps there is
+          // a better way, since APInts are fairly lightweight.
+          return nonlval::ConcreteInt(ValMgr.getValue(ED->getInitVal()));
+        }
+        
+        assert (false &&
+                "ValueDecl support for this ValueDecl not implemented.");
+        
+        return UnknownVal();
+      }
+          
         
         // Integer literals evaluate to an RValue.  Simply retrieve the
         // RValue for the literal.
@@ -278,7 +296,7 @@ LValue ValueStateManager::GetLValue(ValueState St, Expr* E) {
     E = P->getSubExpr();
   
   if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(E))
-    return lval::DeclVal(DR->getDecl());
+    return lval::DeclVal(cast<VarDecl>(DR->getDecl()));
   
   if (UnaryOperator* U = dyn_cast<UnaryOperator>(E))
     if (U->getOpcode() == UnaryOperator::Deref)
index 871d765bd3211e8b39ef51ae5287e9b52e4e43fe..b6e31b9ffeef6713e6b7db626459e396f4ff2d3d 100644 (file)
@@ -203,7 +203,10 @@ protected:
   friend class GRSwitchNodeBuilderImpl;
   
   // Type definitions.
-  typedef llvm::DenseMap<ProgramPoint,void*>        EdgeNodeSetMap;
+  typedef llvm::DenseMap<ProgramPoint, 
+                         llvm::FoldingSet<clang::ExplodedNodeImpl>*> 
+          EdgeNodeSetMap;
+  
   typedef llvm::SmallVector<ExplodedNodeImpl*,2>    RootsTy;
   typedef llvm::SmallVector<ExplodedNodeImpl*,10>   EndNodesTy;
     
index ffb4420965cd07b2724c2586f23abcd9ba3fb08f..a52a776a1d34b1a8d00cd5e430562f023034ab98 100644 (file)
@@ -335,5 +335,10 @@ public:
                              LValue LHS, NonLValue RHS) {
     return TF->EvalBinaryOp(ValMgr, Op, LHS, RHS);
   }
+  
+  inline RValue EvalBinaryOp(ValueManager& ValMgr, BinaryOperator::Opcode Op,
+                             RValue LHS, RValue RHS) {
+    return TF->EvalBinaryOp(ValMgr, Op, LHS, RHS);
+  }
 };
 } // end clang namespace
\ No newline at end of file
index 87ff17037290ccc50d6f238a4a1c9d8df4013ab7..19e87dcd943185b57b155faa9c4a04fbd5c3cb2f 100644 (file)
@@ -47,12 +47,25 @@ public:
                       BinaryOperator::Opcode Op,
                       LValue LHS, LValue RHS);
   
-  
   // Pointer arithmetic.
   
   virtual LValue EvalBinaryOp(ValueManager& ValMgr, BinaryOperator::Opcode Op,
                               LValue LHS, NonLValue RHS) = 0;
   
+  inline RValue EvalBinaryOp(ValueManager& ValMgr, BinaryOperator::Opcode Op,
+                             const RValue& L, const RValue& R) {
+    
+    if (isa<LValue>(L)) {
+      if (isa<LValue>(R))
+        return EvalBinaryOp(ValMgr, Op, cast<LValue>(L), cast<LValue>(R));
+      else
+        return EvalBinaryOp(ValMgr, Op, cast<LValue>(L), cast<NonLValue>(R));
+    }
+    else
+      return EvalBinaryOp(ValMgr, Op, cast<NonLValue>(L), cast<NonLValue>(R));
+  }
+  
+  
   // Equality operators for LValues.
   virtual NonLValue EvalEQ(ValueManager& ValMgr, LValue LHS, LValue RHS) = 0;
   virtual NonLValue EvalNE(ValueManager& ValMgr, LValue LHS, LValue RHS) = 0;
index acf841170d3cf1b6c3d355079308b163bff8e5f8..319270759f5a82ec6fa5f4a1f4635d3e386e62bd 100644 (file)
@@ -474,10 +474,10 @@ namespace lval {
   
   class DeclVal : public LValue {
   public:
-    DeclVal(const ValueDecl* vd) : LValue(DeclValKind,vd) {}
+    DeclVal(const VarDecl* vd) : LValue(DeclValKind, vd) {}
     
-    ValueDecl* getDecl() const {
-      return static_cast<ValueDecl*>(Data);
+    VarDecl* getDecl() const {
+      return static_cast<VarDecl*>(Data);
     }
     
     inline bool operator==(const DeclVal& R) const {