[cfe-commits] r47298 - in /cfe/trunk: Analysis/GRExprEngine.cpp Analysis/RValues.cpp Analysis/ValueState.cpp include/clang/Analysis/PathSensitive/GRExprEngine.h include/clang/Analysis/PathSensitive/RValues.h

Ted Kremenek kremenek at apple.com
Mon Feb 18 17:44:53 PST 2008


Author: kremenek
Date: Mon Feb 18 19:44:53 2008
New Revision: 47298

URL: http://llvm.org/viewvc/llvm-project?rev=47298&view=rev
Log:
Added boilerplate transfer function support for CallExprs.

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

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

==============================================================================
--- cfe/trunk/Analysis/GRExprEngine.cpp (original)
+++ cfe/trunk/Analysis/GRExprEngine.cpp Mon Feb 18 19:44:53 2008
@@ -259,7 +259,7 @@
     do {      
       nonlval::ConcreteInt CaseVal(ValMgr.getValue(V1));
       
-      NonLValue Res = EvalBinaryOp(ValMgr, BinaryOperator::EQ, CondV, CaseVal);
+      NonLValue Res = EvalBinaryOp(BinaryOperator::EQ, CondV, CaseVal);
       
       // Now "assume" that the case matches.
       bool isFeasible = false;
@@ -407,12 +407,51 @@
   Nodify(Dst, D, Pred, SetValue(St, D, GetValue(St, D)));
 }
 
+void GRExprEngine::VisitCall(CallExpr* CE, NodeTy* Pred,
+                             CallExpr::arg_iterator I, CallExpr::arg_iterator E,
+                             NodeSet& Dst) {
+  
+  if (I != E) {
+    NodeSet DstTmp;  
+    Visit(*I, Pred, DstTmp);
+    ++I;
+    
+    for (NodeSet::iterator DI=DstTmp.begin(), DE=DstTmp.end(); DI!=DE; ++DI)
+      VisitCall(CE, *DI, I, E, Dst);
+    
+    return;
+  }
+
+  // If we reach here we have processed all of the arguments.  Evaluate
+  // the callee expression.
+  NodeSet DstTmp;
+  Visit(CE->getCallee(), Pred, DstTmp);
+  
+  // Finally, evaluate the function call.
+  for (NodeSet::iterator DI=DstTmp.begin(), DE=DstTmp.end(); DI!=DE; ++DI) {
+    StateTy St = (*DI)->getState();    
+    LValue L = GetLValue(St, CE->getCallee());
+
+    // Check for uninitialized control-flow.
+    if (isa<UninitializedVal>(L)) {
+      NodeTy* N = Builder->generateNode(CE, St, *DI);
+      N->markAsSink();
+      UninitBranches.insert(N);
+      continue;
+    }
+    
+    // Note: EvalCall must handle the case where the callee is "UnknownVal."
+    Nodify(Dst, CE, *DI, EvalCall(CE, (*DI)->getState()));
+  }
+}
+
 void GRExprEngine::VisitCast(Expr* CastE, Expr* E, NodeTy* Pred, NodeSet& Dst) {
   
   QualType T = CastE->getType();
 
   // Check for redundant casts.
-  if (E->getType() == T) {
+  if (E->getType() == T || 
+      (T->isPointerType() && E->getType()->isFunctionType())) {
     Dst.Add(Pred);
     return;
   }
@@ -515,7 +554,7 @@
       BinaryOperator::Opcode Op = U->isIncrementOp() ? BinaryOperator::Add
                                                      : BinaryOperator::Sub;
       
-      RValue Result = EvalBinaryOp(ValMgr, Op, R1, GetRValueConstant(1U, U));
+      RValue Result = EvalBinaryOp(Op, R1, GetRValueConstant(1U, U));
       
       if (U->isPostfix())
         Nodify(Dst, U, N1, SetValue(SetValue(St, U, R1), L1, Result));
@@ -553,14 +592,14 @@
           const LValue& L1 = cast<LValue>(V1);
           lval::ConcreteInt V2(ValMgr.getZeroWithPtrWidth());
           Nodify(Dst, U, N1,
-                 SetValue(St, U, EvalBinaryOp(ValMgr, BinaryOperator::EQ,
+                 SetValue(St, U, EvalBinaryOp(BinaryOperator::EQ,
                                               L1, V2)));
         }
         else {
           const NonLValue& R1 = cast<NonLValue>(V1);
           nonlval::ConcreteInt V2(ValMgr.getZeroWithPtrWidth());
           Nodify(Dst, U, N1,
-                 SetValue(St, U, EvalBinaryOp(ValMgr, BinaryOperator::EQ,
+                 SetValue(St, U, EvalBinaryOp(BinaryOperator::EQ,
                                               R1, V2)));
         }
         
@@ -705,7 +744,7 @@
           continue;
         }
         
-        Nodify(Dst, B, N2, SetValue(St, B, EvalBinaryOp(ValMgr, Op, V1, V2)));
+        Nodify(Dst, B, N2, SetValue(St, B, EvalBinaryOp(Op, V1, V2)));
         continue;
       
       }
@@ -742,14 +781,14 @@
           
           if (B->getType()->isPointerType()) { // Perform pointer arithmetic.
             const NonLValue& R2 = cast<NonLValue>(V2);
-            Result = EvalBinaryOp(ValMgr, Op, L1, R2);
+            Result = EvalBinaryOp(Op, L1, R2);
           }
           else if (isa<LValue>(V2)) {
             const LValue& L2 = cast<LValue>(V2);
             
             if (B->getRHS()->getType()->isPointerType()) {
               // LValue comparison.
-              Result = EvalBinaryOp(ValMgr, Op, L1, L2);
+              Result = EvalBinaryOp(Op, L1, L2);
             }
             else {
               QualType T1 = B->getLHS()->getType();
@@ -757,7 +796,7 @@
               
               // An operation between two variables of a non-lvalue type.
               Result =
-                EvalBinaryOp(ValMgr, Op,
+                EvalBinaryOp(Op,
                             cast<NonLValue>(GetValue(N1->getState(), L1, &T1)),
                             cast<NonLValue>(GetValue(N2->getState(), L2, &T2)));
             }
@@ -767,7 +806,7 @@
             const NonLValue& R1 = cast<NonLValue>(GetValue(N1->getState(),
                                                            L1, &T));
             const NonLValue& R2 = cast<NonLValue>(V2);
-            Result = EvalBinaryOp(ValMgr, Op, R1, R2);
+            Result = EvalBinaryOp(Op, R1, R2);
           }
           
           Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result));
@@ -821,6 +860,12 @@
       VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
       break;
     }
+      
+    case Stmt::CallExprClass: {
+      CallExpr* C = cast<CallExpr>(S);
+      VisitCall(C, Pred, C->arg_begin(), C->arg_end(), Dst);
+      break;      
+    }
 
     case Stmt::CastExprClass: {
       CastExpr* C = cast<CastExpr>(S);

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

==============================================================================
--- cfe/trunk/Analysis/RValues.cpp (original)
+++ cfe/trunk/Analysis/RValues.cpp Mon Feb 18 19:44:53 2008
@@ -342,7 +342,12 @@
 
     case lval::DeclValKind:
       Out << '&' 
-      << cast<lval::DeclVal>(this)->getDecl()->getIdentifier()->getName();
+          << cast<lval::DeclVal>(this)->getDecl()->getIdentifier()->getName();
+      break;
+      
+    case lval::FuncValKind:
+      Out << "function " 
+          << cast<lval::FuncVal>(this)->getDecl()->getIdentifier()->getName();
       break;
       
     default:

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

==============================================================================
--- cfe/trunk/Analysis/ValueState.cpp (original)
+++ cfe/trunk/Analysis/ValueState.cpp Mon Feb 18 19:44:53 2008
@@ -220,6 +220,8 @@
           // a better way, since APInts are fairly lightweight.
           return nonlval::ConcreteInt(ValMgr.getValue(ED->getInitVal()));
         }
+        else if (FunctionDecl* FD = dyn_cast<FunctionDecl>(D))
+          return lval::FuncVal(FD);
         
         assert (false &&
                 "ValueDecl support for this ValueDecl not implemented.");
@@ -248,7 +250,10 @@
         
       case Stmt::ImplicitCastExprClass: {
         ImplicitCastExpr* C = cast<ImplicitCastExpr>(E);
-        if (C->getType() == C->getSubExpr()->getType()) {
+        QualType CT = C->getType();
+        QualType ST = C->getSubExpr()->getType();
+        
+        if (CT == ST || (CT->isPointerType() && ST->isFunctionType())) {
           E = C->getSubExpr();
           continue;
         }
@@ -257,7 +262,10 @@
         
       case Stmt::CastExprClass: {
         CastExpr* C = cast<CastExpr>(E);
-        if (C->getType() == C->getSubExpr()->getType()) {
+        QualType CT = C->getType();
+        QualType ST = C->getSubExpr()->getType();
+        
+        if (CT == ST || (CT->isPointerType() && ST->isFunctionType())) {
           E = C->getSubExpr();
           continue;
         }
@@ -297,8 +305,14 @@
   while (ParenExpr* P = dyn_cast<ParenExpr>(E))
     E = P->getSubExpr();
   
-  if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(E))
-    return lval::DeclVal(cast<VarDecl>(DR->getDecl()));
+  if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(E)) {
+    ValueDecl* VD = DR->getDecl();
+    
+    if (FunctionDecl* FD = dyn_cast<FunctionDecl>(VD))
+      return lval::FuncVal(FD);
+    else
+      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/GRExprEngine.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h?rev=47298&r1=47297&r2=47298&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h Mon Feb 18 19:44:53 2008
@@ -296,6 +296,11 @@
   
   void VisitAssignmentLHS(Expr* E, NodeTy* Pred, NodeSet& Dst);
   
+  /// VisitCall - Transfer function for function calls.
+  void VisitCall(CallExpr* CE, NodeTy* Pred,
+                 CallExpr::arg_iterator I, CallExpr::arg_iterator E,
+                 NodeSet& Dst);
+  
   /// VisitCast - Transfer function logic for all casts (implicit and explicit).
   void VisitCast(Expr* CastE, Expr* E, NodeTy* Pred, NodeSet& Dst);  
   
@@ -342,7 +347,7 @@
     return TF->EvalComplement(ValMgr, X);
   }
   
-  inline NonLValue EvalBinaryOp(ValueManager& ValMgr, BinaryOperator::Opcode Op,
+  inline NonLValue EvalBinaryOp(BinaryOperator::Opcode Op,
                                 NonLValue LHS, NonLValue RHS) {
     
     if (isa<UninitializedVal>(LHS) || isa<UninitializedVal>(RHS))
@@ -354,7 +359,7 @@
     return TF->EvalBinaryOp(ValMgr, Op, LHS, RHS);
   }    
   
-  inline RValue EvalBinaryOp(ValueManager& ValMgr, BinaryOperator::Opcode Op,
+  inline RValue EvalBinaryOp(BinaryOperator::Opcode Op,
                              LValue LHS, LValue RHS) {
     
     if (isa<UninitializedVal>(LHS) || isa<UninitializedVal>(RHS))
@@ -366,7 +371,7 @@
     return TF->EvalBinaryOp(ValMgr, Op, LHS, RHS);
   }
   
-  inline RValue EvalBinaryOp(ValueManager& ValMgr, BinaryOperator::Opcode Op,
+  inline RValue EvalBinaryOp(BinaryOperator::Opcode Op,
                              LValue LHS, NonLValue RHS) {
     
     if (isa<UninitializedVal>(LHS) || isa<UninitializedVal>(RHS))
@@ -378,7 +383,7 @@
     return TF->EvalBinaryOp(ValMgr, Op, LHS, RHS);
   }
   
-  inline RValue EvalBinaryOp(ValueManager& ValMgr, BinaryOperator::Opcode Op,
+  inline RValue EvalBinaryOp(BinaryOperator::Opcode Op,
                              RValue LHS, RValue RHS) {
     
     if (isa<UninitializedVal>(LHS) || isa<UninitializedVal>(RHS))
@@ -389,5 +394,9 @@
     
     return TF->EvalBinaryOp(ValMgr, Op, LHS, RHS);
   }
+  
+  StateTy EvalCall(CallExpr* CE, StateTy St) {
+    return St;     
+  }
 };
 } // end clang namespace
\ No newline at end of file

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=47298&r1=47297&r2=47298&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/RValues.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/RValues.h Mon Feb 18 19:44:53 2008
@@ -147,9 +147,9 @@
 
 namespace nonlval {
   
-  enum Kind { SymbolValKind,
+  enum Kind { ConcreteIntKind,
+              SymbolValKind,
               SymIntConstraintValKind,
-              ConcreteIntKind,
               NumKind };
 
   class SymbolVal : public NonLValue {
@@ -218,6 +218,7 @@
   enum Kind { SymbolValKind,
               GotoLabelKind,
               DeclValKind,
+              FuncValKind,
               ConcreteIntKind,
               NumKind };
   
@@ -282,6 +283,32 @@
       return V->getSubKind() == DeclValKind;
     }
   };
+  
+  class FuncVal : public LValue {
+  public:
+    FuncVal(const FunctionDecl* fd) : LValue(FuncValKind, fd) {}
+    
+    FunctionDecl* getDecl() const {
+      return static_cast<FunctionDecl*>(Data);
+    }
+    
+    inline bool operator==(const FuncVal& R) const {
+      return getDecl() == R.getDecl();
+    }
+    
+    inline bool operator!=(const FuncVal& R) const {
+      return getDecl() != R.getDecl();
+    }
+    
+    // Implement isa<T> support.
+    static inline bool classof(const RValue* V) {
+      return isa<LValue>(V) && V->getSubKind() == FuncValKind;
+    }
+    
+    static inline bool classof(const LValue* V) {
+      return V->getSubKind() == FuncValKind;
+    }
+  };
 
   class ConcreteInt : public LValue {
   public:





More information about the cfe-commits mailing list