]> granicus.if.org Git - clang/commitdiff
Placed transfer function logic for dereferences in its own method, while at
authorTed Kremenek <kremenek@apple.com>
Wed, 20 Feb 2008 04:02:35 +0000 (04:02 +0000)
committerTed Kremenek <kremenek@apple.com>
Wed, 20 Feb 2008 04:02:35 +0000 (04:02 +0000)
the same time clearing up some logic of how the unary '*' operator is processed.

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

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

index ef3664ef4314d08a976a24955b1addbc462be73b..243c0788769776e300361e59c5d0473e65cdf658 100644 (file)
@@ -528,32 +528,124 @@ void GRExprEngine::VisitSizeOfAlignOfTypeExpr(SizeOfAlignOfTypeExpr* S,
   
 }
 
-void GRExprEngine::VisitUnaryOperator(UnaryOperator* U,
-                                     GRExprEngine::NodeTy* Pred,
-                                     GRExprEngine::NodeSet& Dst) {
+void GRExprEngine::VisitDeref(UnaryOperator* U, NodeTy* Pred, NodeSet& Dst) {
+
+  Expr* E = U->getSubExpr()->IgnoreParens();
+    
+  NodeSet DstTmp;
   
-  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);
+  if (!isa<DeclRefExpr>(E))
+    DstTmp.Add(Pred);
   else
-    Visit(U->getSubExpr(), Pred, S1);
+    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,
+                                      NodeTy* Pred, NodeSet& Dst) {
+  
+  NodeSet 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 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U,
         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 @@ void GRExprEngine::VisitAssignmentLHS(Expr* E, GRExprEngine::NodeTy* Pred,
   
   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 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
   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 @@ void GRExprEngine::Visit(Stmt* S, NodeTy* Pred, NodeSet& Dst) {
       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;
+    }
   }
 }
 
index 0fc03dda588360acb6f37f7eef24aa5e95bcbe3a..60277300718966d787dbb82475b733524f894033 100644 (file)
@@ -240,7 +240,7 @@ LValue LValue::GetValue(AddrLabelExpr* E) {
 // Pretty-Printing.
 //===----------------------------------------------------------------------===//
 
-void RValue::print() const {
+void RValue::printStdErr() const {
   print(*llvm::cerr.stream());
 }
 
index 5796238d48d3bc1c54bb217319c441610c825c0a..d756980306c31c9d9809a40b75d2cc77a1f5409e 100644 (file)
@@ -310,9 +310,8 @@ RValue ValueStateManager::GetValue(ValueState St, Expr* E, bool* hasVal) {
 
 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 @@ LValue ValueStateManager::GetLValue(ValueState St, Expr* E) {
   }
   
   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));
 }
 
index d4c9932c066ff7f96a246b9f864bb36e67460071..5ae8012c07f74f79f23fb75d2dbcb7a669dd71bc 100644 (file)
@@ -299,7 +299,7 @@ public:
   /// 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 @@ public:
   /// 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))
index cd78008aae88a75f1701653b14bb1eb11633933d..8c3b8197f321d82bf0cfe4b8bf34d67cfc1dce82 100644 (file)
@@ -72,7 +72,7 @@ public:
   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;