[cfe-commits] r50071 - in /cfe/trunk: include/clang/Analysis/PathSensitive/GRExprEngine.h lib/Analysis/GRExprEngine.cpp

Ted Kremenek kremenek at apple.com
Mon Apr 21 16:43:38 PDT 2008


Author: kremenek
Date: Mon Apr 21 18:43:38 2008
New Revision: 50071

URL: http://llvm.org/viewvc/llvm-project?rev=50071&view=rev
Log:
Added support for detected bad dereferences involving MemberExprs, e.g. x->f where "x" is NULL.

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

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=50071&r1=50070&r2=50071&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h Mon Apr 21 18:43:38 2008
@@ -479,6 +479,13 @@
   ///  other functions that handle specific kinds of statements.
   void Visit(Stmt* S, NodeTy* Pred, NodeSet& Dst);
   
+  /// VisitLVal - Similar to Visit, but the specified expression is assummed
+  ///  to be evaluated under the context where it evaluates to an LVal.  For
+  ///  example, if Ex is a DeclRefExpr, under Visit Ex would evaluate to the
+  ///  value bound to Ex in the symbolic state, while under VisitLVal it would
+  ///  evaluate to an LVal representing the location of the referred Decl.
+  void VisitLVal(Expr* Ex, NodeTy* Pred, NodeSet& Dst);
+  
   /// VisitAsmStmt - Transfer function logic for inline asm.
   void VisitAsmStmt(AsmStmt* A, NodeTy* Pred, NodeSet& Dst);
   
@@ -494,25 +501,13 @@
   
   /// VisitBinaryOperator - Transfer function logic for binary operators.
   void VisitBinaryOperator(BinaryOperator* B, NodeTy* Pred, NodeSet& Dst);
-  
-  void VisitLVal(Expr* Ex, NodeTy* Pred, NodeSet& Dst);
+
   
   /// VisitCall - Transfer function for function calls.
   void VisitCall(CallExpr* CE, NodeTy* Pred,
                  CallExpr::arg_iterator AI, CallExpr::arg_iterator AE,
                  NodeSet& Dst);
   
-  /// VisitObjCMessageExpr - Transfer function for ObjC message expressions.
-  void VisitObjCMessageExpr(ObjCMessageExpr* ME, NodeTy* Pred, NodeSet& Dst);
-  
-  void VisitObjCMessageExprArgHelper(ObjCMessageExpr* ME,
-                                     ObjCMessageExpr::arg_iterator I,
-                                     ObjCMessageExpr::arg_iterator E,
-                                     NodeTy* Pred, NodeSet& Dst);
-  
-  void VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME, NodeTy* Pred,
-                                          NodeSet& Dst);
-  
   /// VisitCast - Transfer function logic for all casts (implicit and explicit).
   void VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst);  
   
@@ -522,12 +517,36 @@
   /// VisitDeclStmt - Transfer function logic for DeclStmts.
   void VisitDeclStmt(DeclStmt* DS, NodeTy* Pred, NodeSet& Dst); 
   
+  void VisitDeref(UnaryOperator* U, NodeTy* Pred, NodeSet& Dst,
+                  bool GetLVal = false);
+  
+  void VisitDeref(Expr* Ex, RVal V, ValueState* St, NodeTy* Pred, NodeSet& Dst,
+                  bool GetLVal);
+  
   /// VisitGuardedExpr - Transfer function logic for ?, __builtin_choose
   void VisitGuardedExpr(Expr* Ex, Expr* L, Expr* R, NodeTy* Pred, NodeSet& Dst);
   
   /// VisitLogicalExpr - Transfer function logic for '&&', '||'
   void VisitLogicalExpr(BinaryOperator* B, NodeTy* Pred, NodeSet& Dst);
   
+  /// VisitMemberExpr - Transfer function for member expressions.
+  void VisitMemberExpr(MemberExpr* M, NodeTy* Pred, NodeSet& Dst, bool asLVal);
+  
+  void VisitMemberExprField(MemberExpr* M, Expr* Base, NodeTy* Pred,
+                            NodeSet& Dst, bool asLVal);
+    
+  
+  /// VisitObjCMessageExpr - Transfer function for ObjC message expressions.
+  void VisitObjCMessageExpr(ObjCMessageExpr* ME, NodeTy* Pred, NodeSet& Dst);
+  
+  void VisitObjCMessageExprArgHelper(ObjCMessageExpr* ME,
+                                     ObjCMessageExpr::arg_iterator I,
+                                     ObjCMessageExpr::arg_iterator E,
+                                     NodeTy* Pred, NodeSet& Dst);
+  
+  void VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME, NodeTy* Pred,
+                                          NodeSet& Dst);
+  
   /// VisitReturnStmt - Transfer function logic for return statements.
   void VisitReturnStmt(ReturnStmt* R, NodeTy* Pred, NodeSet& Dst);
   
@@ -541,8 +560,8 @@
   /// VisitUnaryOperator - Transfer function logic for unary operators.
   void VisitUnaryOperator(UnaryOperator* B, NodeTy* Pred, NodeSet& Dst);
   
-  void VisitDeref(UnaryOperator* U, NodeTy* Pred, NodeSet& Dst,
-                  bool GetLVal = false);
+  
+  
   
   RVal EvalCast(RVal X, QualType CastT) {
     if (X.isUnknownOrUndef())
@@ -554,6 +573,8 @@
       return TF->EvalCast(*this, cast<NonLVal>(X), CastT);
   }
   
+
+  
   RVal EvalMinus(UnaryOperator* U, RVal X) {
     return X.isValid() ? TF->EvalMinus(*this, U, cast<NonLVal>(X)) : X;
   }

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

==============================================================================
--- cfe/trunk/lib/Analysis/GRExprEngine.cpp (original)
+++ cfe/trunk/lib/Analysis/GRExprEngine.cpp Mon Apr 21 18:43:38 2008
@@ -285,6 +285,11 @@
       break;
     }
       
+    case Stmt::MemberExprClass: {
+      VisitMemberExpr(cast<MemberExpr>(S), Pred, Dst, false);
+      break;
+    }
+      
     case Stmt::ObjCMessageExprClass: {
       VisitObjCMessageExpr(cast<ObjCMessageExpr>(S), Pred, Dst);
       break;
@@ -709,6 +714,36 @@
   MakeNode(Dst, D, Pred, SetBlkExprRVal(St, D, Y));
 }
 
+/// VisitMemberExpr - Transfer function for member expressions.
+void GRExprEngine::VisitMemberExpr(MemberExpr* M, NodeTy* Pred,
+                                   NodeSet& Dst, bool asLVal) {
+  
+  Expr* Base = M->getBase()->IgnoreParens();
+
+  NodeSet Tmp;
+  VisitLVal(Base, Pred, Tmp);
+  
+  if (Base->getType()->isPointerType()) {
+    NodeSet Tmp2;
+    
+    for (NodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
+      ValueState* St = GetState(*I);      
+      VisitDeref(Base, GetRVal(St, Base), St, *I, Tmp2, true);
+    }
+    
+    for (NodeSet::iterator I=Tmp2.begin(), E=Tmp2.end(); I!=E; ++I)
+      VisitMemberExprField(M, Base, *I, Dst, asLVal);
+  }
+  else
+    for (NodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I)
+      VisitMemberExprField(M, Base, *I, Dst, asLVal);
+}
+
+void GRExprEngine::VisitMemberExprField(MemberExpr* M, Expr* Base, NodeTy* Pred,
+                                        NodeSet& Dst, bool asLVal) {
+  Dst.Add(Pred);  
+}
+
 void GRExprEngine::EvalStore(NodeSet& Dst, Expr* E, NodeTy* Pred,
                              ValueState* St, RVal TargetLV, RVal Val) {
   
@@ -1149,9 +1184,9 @@
 
 void GRExprEngine::VisitDeref(UnaryOperator* U, NodeTy* Pred,
                               NodeSet& Dst, bool GetLVal) {
-
+  
   Expr* Ex = U->getSubExpr()->IgnoreParens();
-    
+  
   NodeSet DstTmp;
   
   if (isa<DeclRefExpr>(Ex))
@@ -1160,82 +1195,80 @@
     Visit(Ex, Pred, DstTmp);
   
   for (NodeSet::iterator I = DstTmp.begin(), DE = DstTmp.end(); I != DE; ++I) {
-
-    NodeTy* N = *I;
-    ValueState* St = GetState(N);
-    
-    // FIXME: Bifurcate when dereferencing a symbolic with no constraints?
-    
+    ValueState* St = GetState(Pred);
     RVal V = GetRVal(St, Ex);
-    
-    // Check for dereferences of undefined values.
-    
-    if (V.isUndef()) {
-      
-      NodeTy* Succ = Builder->generateNode(U, St, N);
-      
-      if (Succ) {
-        Succ->markAsSink();
-        UndefDeref.insert(Succ);
-      }
-      
-      continue;
-    }
-    
-    // Check for dereferences of unknown values.  Treat as No-Ops.
-    
-    if (V.isUnknown()) {
-      Dst.Add(N);
-      continue;
+    VisitDeref(U, V, St, Pred, Dst, GetLVal);
+  }
+}
+
+void GRExprEngine::VisitDeref(Expr* Ex, RVal V, ValueState* St, NodeTy* Pred,
+                              NodeSet& Dst, bool GetLVal) {
+  
+  // Check for dereferences of undefined values.
+  
+  if (V.isUndef()) {
+    if (NodeTy* Succ = Builder->generateNode(Ex, St, Pred)) {
+      Succ->markAsSink();
+      UndefDeref.insert(Succ);
     }
     
-    // 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.
-    
-    LVal LV = cast<LVal>(V);    
-    bool isFeasibleNotNull;
-    
-    // "Assume" that the pointer is Not-NULL.
-    
-    ValueState* StNotNull = Assume(St, LV, true, isFeasibleNotNull);
+    return;
+  }
+  
+  // Check for dereferences of unknown values.  Treat as No-Ops.
+  
+  if (V.isUnknown()) {
+    Dst.Add(Pred);
+    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.
+  
+  LVal LV = cast<LVal>(V);    
+  bool isFeasibleNotNull;
+  
+  // "Assume" that the pointer is Not-NULL.
+  
+  ValueState* StNotNull = Assume(St, LV, true, isFeasibleNotNull);
+  
+  if (isFeasibleNotNull) {
     
-    if (isFeasibleNotNull) {
-
-      if (GetLVal) MakeNode(Dst, U, N, SetRVal(StNotNull, U, LV));
-      else {
-        
-        // FIXME: Currently symbolic analysis "generates" new symbols
-        //  for the contents of values.  We need a better approach.
+    if (GetLVal)
+      MakeNode(Dst, Ex, Pred, SetRVal(StNotNull, Ex, LV));
+    else {
       
-        MakeNode(Dst, U, N, SetRVal(StNotNull, U,
-                                  GetRVal(StNotNull, LV, U->getType())));
-      }
+      // FIXME: Currently symbolic analysis "generates" new symbols
+      //  for the contents of values.  We need a better approach.
+      
+      MakeNode(Dst, Ex, Pred,
+               SetRVal(StNotNull, Ex, GetRVal(StNotNull, LV, Ex->getType())));
     }
+  }
+  
+  bool isFeasibleNull;
+  
+  // Now "assume" that the pointer is NULL.
+  
+  ValueState* StNull = Assume(St, LV, false, isFeasibleNull);
+  
+  if (isFeasibleNull) {
     
-    bool isFeasibleNull;
-    
-    // Now "assume" that the pointer is NULL.
+    // We don't use "MakeNode" here because the node will be a sink
+    // and we have no intention of processing it later.
     
-    ValueState* StNull = Assume(St, LV, false, isFeasibleNull);
+    NodeTy* NullNode = Builder->generateNode(Ex, StNull, Pred);
     
-    if (isFeasibleNull) {
+    if (NullNode) {
       
-      // We don't use "MakeNode" here because the node will be a sink
-      // and we have no intention of processing it later.
-
-      NodeTy* NullNode = Builder->generateNode(U, StNull, N);
+      NullNode->markAsSink();
       
-      if (NullNode) {
-
-        NullNode->markAsSink();
-        
-        if (isFeasibleNotNull) ImplicitNullDeref.insert(NullNode);
-        else ExplicitNullDeref.insert(NullNode);
-      }
-    }    
+      if (isFeasibleNotNull) ImplicitNullDeref.insert(NullNode);
+      else ExplicitNullDeref.insert(NullNode);
+    }
   }
 }
 
@@ -1387,23 +1420,36 @@
 
 void GRExprEngine::VisitLVal(Expr* Ex, NodeTy* Pred, NodeSet& Dst) {
 
-  if (Ex != CurrentStmt && getCFG().isBlkExpr(Ex)) {
-    Dst.Add(Pred);
-    return;
-  }
-  
   Ex = Ex->IgnoreParens();
-  
-  if (isa<DeclRefExpr>(Ex)) {
+
+  if (Ex != CurrentStmt && getCFG().isBlkExpr(Ex)) {
     Dst.Add(Pred);
     return;
   }
   
-  if (UnaryOperator* U = dyn_cast<UnaryOperator>(Ex))
-    if (U->getOpcode() == UnaryOperator::Deref) {
-      VisitDeref(U, Pred, Dst, true);
+  switch (Ex->getStmtClass()) {
+    default:
+      break;
+      
+    case Stmt::DeclRefExprClass:
+      Dst.Add(Pred);
       return;
+      
+    case Stmt::UnaryOperatorClass: {
+      UnaryOperator* U = cast<UnaryOperator>(Ex);
+      
+      if (U->getOpcode() == UnaryOperator::Deref) {
+        VisitDeref(U, Pred, Dst, true);
+        return;
+      }
+      
+      break;
     }
+      
+    case Stmt::MemberExprClass:
+      VisitMemberExpr(cast<MemberExpr>(Ex), Pred, Dst, true);
+      return;
+  }
   
   Visit(Ex, Pred, Dst);
 }





More information about the cfe-commits mailing list