[cfe-commits] r47183 - in /cfe/trunk: 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

Ted Kremenek kremenek at apple.com
Fri Feb 15 14:09:30 PST 2008


Author: kremenek
Date: Fri Feb 15 16:09:30 2008
New Revision: 47183

URL: http://llvm.org/viewvc/llvm-project?rev=47183&view=rev
Log:
Simplified transfer function logic for ++/-- operators.
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.

Modified:
    cfe/trunk/Analysis/ExplodedGraph.cpp
    cfe/trunk/Analysis/GRExprEngine.cpp
    cfe/trunk/Analysis/RValues.cpp
    cfe/trunk/Analysis/ValueState.cpp
    cfe/trunk/include/clang/Analysis/PathSensitive/ExplodedGraph.h
    cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h
    cfe/trunk/include/clang/Analysis/PathSensitive/GRTransferFuncs.h
    cfe/trunk/include/clang/Analysis/PathSensitive/RValues.h

Modified: cfe/trunk/Analysis/ExplodedGraph.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Analysis/ExplodedGraph.cpp?rev=47183&r1=47182&r2=47183&view=diff

==============================================================================
--- cfe/trunk/Analysis/ExplodedGraph.cpp (original)
+++ cfe/trunk/Analysis/ExplodedGraph.cpp Fri Feb 15 16:09:30 2008
@@ -75,8 +75,7 @@
   // 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)

Modified: cfe/trunk/Analysis/GRExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Analysis/GRExprEngine.cpp?rev=47183&r1=47182&r2=47183&view=diff

==============================================================================
--- cfe/trunk/Analysis/GRExprEngine.cpp (original)
+++ cfe/trunk/Analysis/GRExprEngine.cpp Fri Feb 15 16:09:30 2008
@@ -387,8 +387,7 @@
   
   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 @@
     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 @@
           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 @@
           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);

Modified: cfe/trunk/Analysis/RValues.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Analysis/RValues.cpp?rev=47183&r1=47182&r2=47183&view=diff

==============================================================================
--- cfe/trunk/Analysis/RValues.cpp (original)
+++ cfe/trunk/Analysis/RValues.cpp Fri Feb 15 16:09:30 2008
@@ -428,11 +428,23 @@
 }
 
 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.");
   }        
 }

Modified: cfe/trunk/Analysis/ValueState.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Analysis/ValueState.cpp?rev=47183&r1=47182&r2=47183&view=diff

==============================================================================
--- cfe/trunk/Analysis/ValueState.cpp (original)
+++ cfe/trunk/Analysis/ValueState.cpp Fri Feb 15 16:09:30 2008
@@ -91,7 +91,8 @@
     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 @@
         // 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 @@
     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)

Modified: cfe/trunk/include/clang/Analysis/PathSensitive/ExplodedGraph.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/ExplodedGraph.h?rev=47183&r1=47182&r2=47183&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/ExplodedGraph.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/ExplodedGraph.h Fri Feb 15 16:09:30 2008
@@ -203,7 +203,10 @@
   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;
     

Modified: cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h?rev=47183&r1=47182&r2=47183&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h Fri Feb 15 16:09:30 2008
@@ -335,5 +335,10 @@
                              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

Modified: cfe/trunk/include/clang/Analysis/PathSensitive/GRTransferFuncs.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/GRTransferFuncs.h?rev=47183&r1=47182&r2=47183&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/GRTransferFuncs.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/GRTransferFuncs.h Fri Feb 15 16:09:30 2008
@@ -47,12 +47,25 @@
                       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;

Modified: cfe/trunk/include/clang/Analysis/PathSensitive/RValues.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/RValues.h?rev=47183&r1=47182&r2=47183&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/RValues.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/RValues.h Fri Feb 15 16:09:30 2008
@@ -474,10 +474,10 @@
   
   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 {





More information about the cfe-commits mailing list