[cfe-commits] r47356 - 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
Tue Feb 19 20:02:36 PST 2008


Author: kremenek
Date: Tue Feb 19 22:02:35 2008
New Revision: 47356

URL: http://llvm.org/viewvc/llvm-project?rev=47356&view=rev
Log:
Placed transfer function logic for dereferences in its own method, while at
the same time clearing up some logic of how the unary '*' operator is processed.

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=47356&r1=47355&r2=47356&view=diff

==============================================================================
--- cfe/trunk/Analysis/GRExprEngine.cpp (original)
+++ cfe/trunk/Analysis/GRExprEngine.cpp Tue Feb 19 22:02:35 2008
@@ -528,32 +528,124 @@
   
 }
 
+void GRExprEngine::VisitDeref(UnaryOperator* U, NodeTy* Pred, NodeSet& Dst) {
+
+  Expr* E = U->getSubExpr()->IgnoreParens();
+    
+  NodeSet DstTmp;
+  
+  if (!isa<DeclRefExpr>(E))
+    DstTmp.Add(Pred);
+  else
+    Visit(E, Pred, DstTmp);
+  
+  for (NodeSet::iterator I=DstTmp.begin(), DE=DstTmp.end(); I != DE; ++I) {
+
+    NodeTy* N = *I;
+    StateTy St = N->getState();
+    
+    // FIXME: Bifurcate when dereferencing a symbolic with no constraints?
+    
+    LValue L = cast<LValue>(GetValue(St, E));
+    
+    if (isa<UninitializedVal>(L)) {
+      NodeTy* Succ = Builder->generateNode(U, St, N);
+      
+      if (Succ) {
+        Succ->markAsSink();
+        UninitDeref.insert(Succ);
+      }
+      
+      continue;
+    }
+    
+    if (L.isUnknown()) {
+      Dst.Add(N);
+      continue;
+    }
+    
+    // After a dereference, one of two possible situations arise:
+    //  (1) A crash, because the pointer was NULL.
+    //  (2) The pointer is not NULL, and the dereference works.
+    // 
+    // We add these assumptions.
+    
+    bool isFeasibleNotNull;
+    
+    // "Assume" that the pointer is Not-NULL.
+    StateTy StNotNull = Assume(St, L, true, isFeasibleNotNull);
+    
+    if (isFeasibleNotNull) {
+      QualType T = U->getType();
+      
+      // FIXME: Currently symbolic analysis "generates" new symbols
+      //  for the contents of values.  We need a better approach.
+      
+      Nodify(Dst, U, N, SetValue(StNotNull, U, GetValue(StNotNull, L, &T)));
+    }
+    
+    bool isFeasibleNull;
+    
+    // "Assume" that the pointer is NULL.
+    StateTy StNull = Assume(St, L, false, isFeasibleNull);
+    
+    if (isFeasibleNull) {
+      // We don't use "Nodify" here because the node will be a sink
+      // and we have no intention of processing it later.
+      NodeTy* NullNode = Builder->generateNode(U, StNull, N);
+      
+      if (NullNode) {
+        NullNode->markAsSink();
+        
+        if (isFeasibleNotNull)
+          ImplicitNullDeref.insert(NullNode);
+        else
+          ExplicitNullDeref.insert(NullNode);
+      }
+    }    
+  }
+}
+
 void GRExprEngine::VisitUnaryOperator(UnaryOperator* U,
-                                     GRExprEngine::NodeTy* Pred,
-                                     GRExprEngine::NodeSet& Dst) {
+                                      NodeTy* Pred, NodeSet& Dst) {
   
   NodeSet S1;
-  UnaryOperator::Opcode Op = U->getOpcode();
   
-  // FIXME: This is a hack so that for '*' and '&' we don't recurse
-  //  on visiting the subexpression if it is a DeclRefExpr.  We should
-  //  probably just handle AddrOf and Deref in their own methods to make
-  //  this cleaner.
-  if ((Op == UnaryOperator::Deref || Op == UnaryOperator::AddrOf) &&
-      isa<DeclRefExpr>(U->getSubExpr()))
-    S1.Add(Pred);
-  else
-    Visit(U->getSubExpr(), Pred, S1);
-    
+  assert (U->getOpcode() != UnaryOperator::Deref);
+  
+  switch (U->getOpcode()) {
+    case UnaryOperator::PostInc:
+    case UnaryOperator::PostDec:
+    case UnaryOperator::PreInc:
+    case UnaryOperator::PreDec:
+    case UnaryOperator::AddrOf:
+      // Evalue subexpression as an LValue.
+      VisitLValue(U->getSubExpr(), Pred, S1);
+      break;
+      
+    case UnaryOperator::SizeOf:
+    case UnaryOperator::AlignOf:
+      // Do not evaluate subexpression.
+      S1.Add(Pred);
+      break;
+      
+    default:
+      Visit(U->getSubExpr(), Pred, S1);
+      break;
+  }
+
   for (NodeSet::iterator I1=S1.begin(), E1=S1.end(); I1 != E1; ++I1) {
+
     NodeTy* N1 = *I1;
     StateTy St = N1->getState();
     
-    // Handle ++ and -- (both pre- and post-increment).
-    
     if (U->isIncrementDecrementOp()) {
+      
+      // Handle ++ and -- (both pre- and post-increment).
+      
       const LValue& L1 = GetLValue(St, U->getSubExpr());
-      RValue R1 = GetValue(St, L1);
+      QualType T = U->getType();
+      RValue R1 = GetValue(St, L1, &T);
       
       BinaryOperator::Opcode Op = U->isIncrementOp() ? BinaryOperator::Add
                                                      : BinaryOperator::Sub;
@@ -634,77 +726,17 @@
         Nodify(Dst, U, N1, SetValue(St, U, L1));
         break;
       }
-        
-      case UnaryOperator::Deref: {
-        // FIXME: Stop when dereferencing an uninitialized value.
-        // FIXME: Bifurcate when dereferencing a symbolic with no constraints?
-        
-        const RValue& V = GetValue(St, U->getSubExpr());        
-        const LValue& L1 = cast<LValue>(V);
-        
-        if (isa<UninitializedVal>(L1)) {
-          NodeTy* N = Builder->generateNode(U, St, N1);
-          
-          if (N) {
-            N->markAsSink();
-            UninitDeref.insert(N);            
-          }
-          
-          return;
-        }
-        
-        // After a dereference, one of two possible situations arise:
-        //  (1) A crash, because the pointer was NULL.
-        //  (2) The pointer is not NULL, and the dereference works.
-        // 
-        // We add these assumptions.
                 
-        bool isFeasibleNotNull;
-       
-        // "Assume" that the pointer is Not-NULL.
-        StateTy StNotNull = Assume(St, L1, true, isFeasibleNotNull);
-        
-        if (isFeasibleNotNull) {
-          QualType T = U->getType();
-          Nodify(Dst, U, N1, SetValue(StNotNull, U,
-                                      GetValue(StNotNull, L1, &T)));
-        }
-        
-        if (V.isUnknown())
-          return;
-        
-        bool isFeasibleNull;
-        
-        // "Assume" that the pointer is NULL.
-        StateTy StNull = Assume(St, L1, false, isFeasibleNull);
-        
-        if (isFeasibleNull) {
-          // We don't use "Nodify" here because the node will be a sink
-          // and we have no intention of processing it later.
-          NodeTy* NullNode = Builder->generateNode(U, StNull, N1);
-
-          if (NullNode) {
-            NullNode->markAsSink();
-            
-            if (isFeasibleNotNull)
-              ImplicitNullDeref.insert(NullNode);
-            else
-              ExplicitNullDeref.insert(NullNode);
-          }
-        }
-        
-        break;
-      }
-        
       default: ;
         assert (false && "Not implemented.");
     }    
   }
 }
 
-void GRExprEngine::VisitAssignmentLHS(Expr* E, GRExprEngine::NodeTy* Pred,
-                                     GRExprEngine::NodeSet& Dst) {
-
+void GRExprEngine::VisitLValue(Expr* E, NodeTy* Pred, NodeSet& Dst) {
+  
+  E = E->IgnoreParens();
+  
   if (isa<DeclRefExpr>(E)) {
     Dst.Add(Pred);
     return;
@@ -712,7 +744,13 @@
   
   if (UnaryOperator* U = dyn_cast<UnaryOperator>(E)) {
     if (U->getOpcode() == UnaryOperator::Deref) {
-      Visit(U->getSubExpr(), Pred, Dst);
+      E = U->getSubExpr()->IgnoreParens();
+      
+      if (isa<DeclRefExpr>(E))
+        Dst.Add(Pred);
+      else
+        Visit(E, Pred, Dst);
+      
       return;
     }
   }
@@ -726,7 +764,7 @@
   NodeSet S1;
   
   if (B->isAssignmentOp())
-    VisitAssignmentLHS(B->getLHS(), Pred, S1);
+    VisitLValue(B->getLHS(), Pred, S1);
   else
     Visit(B->getLHS(), Pred, S1);
 
@@ -974,9 +1012,16 @@
       break;
     }
       
-    case Stmt::UnaryOperatorClass:
-      VisitUnaryOperator(cast<UnaryOperator>(S), Pred, Dst);
+    case Stmt::UnaryOperatorClass: {
+      UnaryOperator* U = cast<UnaryOperator>(S);
+      
+      if (U->getOpcode() == UnaryOperator::Deref)
+        VisitDeref(U, Pred, Dst);
+      else
+        VisitUnaryOperator(U, Pred, Dst);
+      
       break;
+    }
   }
 }
 

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

==============================================================================
--- cfe/trunk/Analysis/RValues.cpp (original)
+++ cfe/trunk/Analysis/RValues.cpp Tue Feb 19 22:02:35 2008
@@ -240,7 +240,7 @@
 // Pretty-Printing.
 //===----------------------------------------------------------------------===//
 
-void RValue::print() const {
+void RValue::printStdErr() const {
   print(*llvm::cerr.stream());
 }
 

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

==============================================================================
--- cfe/trunk/Analysis/ValueState.cpp (original)
+++ cfe/trunk/Analysis/ValueState.cpp Tue Feb 19 22:02:35 2008
@@ -310,9 +310,8 @@
 
 LValue ValueStateManager::GetLValue(ValueState St, Expr* E) {
   
-  while (ParenExpr* P = dyn_cast<ParenExpr>(E))
-    E = P->getSubExpr();
-  
+  E = E->IgnoreParens();
+
   if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(E)) {
     ValueDecl* VD = DR->getDecl();
     
@@ -323,9 +322,17 @@
   }
   
   if (UnaryOperator* U = dyn_cast<UnaryOperator>(E))
-    if (U->getOpcode() == UnaryOperator::Deref)
-      return cast<LValue>(GetValue(St, U->getSubExpr()));
-  
+    if (U->getOpcode() == UnaryOperator::Deref) {
+      E = U->getSubExpr()->IgnoreParens();
+        
+      if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(E)) {
+        lval::DeclVal X(cast<VarDecl>(DR->getDecl()));
+        return cast<LValue>(GetValue(St, X));
+      }
+      else
+        return cast<LValue>(GetValue(St, E));
+    }
+        
   return cast<LValue>(GetValue(St, E));
 }
 

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=47356&r1=47355&r2=47356&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h Tue Feb 19 22:02:35 2008
@@ -299,7 +299,7 @@
   /// VisitBinaryOperator - Transfer function logic for binary operators.
   void VisitBinaryOperator(BinaryOperator* B, NodeTy* Pred, NodeSet& Dst);
   
-  void VisitAssignmentLHS(Expr* E, NodeTy* Pred, NodeSet& Dst);
+  void VisitLValue(Expr* E, NodeTy* Pred, NodeSet& Dst);
   
   /// VisitCall - Transfer function for function calls.
   void VisitCall(CallExpr* CE, NodeTy* Pred,
@@ -329,6 +329,8 @@
   /// VisitUnaryOperator - Transfer function logic for unary operators.
   void VisitUnaryOperator(UnaryOperator* B, NodeTy* Pred, NodeSet& Dst);
   
+  void VisitDeref(UnaryOperator* B, NodeTy* Pred, NodeSet& Dst);
+  
   
   inline RValue EvalCast(ValueManager& ValMgr, RValue X, Expr* CastExpr) {
     if (isa<UnknownVal>(X) || isa<UninitializedVal>(X))

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=47356&r1=47355&r2=47356&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/RValues.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/RValues.h Tue Feb 19 22:02:35 2008
@@ -72,7 +72,7 @@
   inline bool isUnknown() const { return getRawKind() == UnknownKind; }
   
   void print(std::ostream& OS) const;
-  void print() const;
+  void printStdErr() const;
   
   typedef const SymbolID* symbol_iterator;
   symbol_iterator symbol_begin() const;





More information about the cfe-commits mailing list