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

Ted Kremenek kremenek at apple.com
Tue Apr 15 16:06:53 PDT 2008


Author: kremenek
Date: Tue Apr 15 18:06:53 2008
New Revision: 49752

URL: http://llvm.org/viewvc/llvm-project?rev=49752&view=rev
Log:
Added some comments to GRExprEngine.  Reorder some of the method definitions
to start logically organizing them.

Added initial plug-in transfer function support for Objective-C message expressions.

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

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=49752&r1=49751&r2=49752&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h Tue Apr 15 18:06:53 2008
@@ -594,7 +594,12 @@
   
   void EvalCall(NodeSet& Dst, CallExpr* CE, LVal L, NodeTy* Pred) {
     assert (Builder && "GRStmtNodeBuilder must be defined.");    
-    return TF->EvalCall(Dst, *this, *Builder, CE, L, Pred);
+    TF->EvalCall(Dst, *this, *Builder, CE, L, Pred);
+  }
+  
+  void EvalObjCMessageExpr(NodeSet& Dst, ObjCMessageExpr* ME, NodeTy* Pred) {    
+    assert (Builder && "GRStmtNodeBuilder must be defined.");
+    TF->EvalObjCMessageExpr(Dst, *this, *Builder, ME, Pred);
   }
   
   ValueState* MarkBranch(ValueState* St, Stmt* Terminator, bool branchTaken);

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=49752&r1=49751&r2=49752&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/GRTransferFuncs.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/GRTransferFuncs.h Tue Apr 15 18:06:53 2008
@@ -66,6 +66,12 @@
                         CallExpr* CE, LVal L,
                         ExplodedNode<ValueState>* Pred) = 0;
   
+  virtual void EvalObjCMessageExpr(ExplodedNodeSet<ValueState>& Dst,
+                                   GRExprEngine& Engine,
+                                   GRStmtNodeBuilder<ValueState>& Builder,
+                                   ObjCMessageExpr* ME,
+                                   ExplodedNode<ValueState>* Pred) = 0;
+  
   // End-of-path.
   
   virtual void EvalEndPath(GRExprEngine& Engine,

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

==============================================================================
--- cfe/trunk/lib/Analysis/GRExprEngine.cpp (original)
+++ cfe/trunk/lib/Analysis/GRExprEngine.cpp Tue Apr 15 18:06:53 2008
@@ -23,23 +23,15 @@
 #include <sstream>
 #endif
 
-// SaveAndRestore - A utility class that uses RIIA to save and restore
-//  the value of a variable.
-template<typename T>
-struct VISIBILITY_HIDDEN SaveAndRestore {
-  SaveAndRestore(T& x) : X(x), old_value(x) {}
-  ~SaveAndRestore() { X = old_value; }
-  T get() { return old_value; }
-  
-  T& X;
-  T old_value;
-};
-
 using namespace clang;
 using llvm::dyn_cast;
 using llvm::cast;
 using llvm::APSInt;
 
+//===----------------------------------------------------------------------===//
+// Engine construction and deletion.
+//===----------------------------------------------------------------------===//
+
 
 GRExprEngine::GRExprEngine(CFG& cfg, Decl& CD, ASTContext& Ctx)
   : CoreEngine(cfg, CD, Ctx, *this), 
@@ -70,6 +62,22 @@
     delete *I;  
 }
 
+//===----------------------------------------------------------------------===//
+// Utility methods.
+//===----------------------------------------------------------------------===//
+
+// SaveAndRestore - A utility class that uses RIIA to save and restore
+//  the value of a variable.
+template<typename T>
+struct VISIBILITY_HIDDEN SaveAndRestore {
+  SaveAndRestore(T& x) : X(x), old_value(x) {}
+  ~SaveAndRestore() { X = old_value; }
+  T get() { return old_value; }
+  
+  T& X;
+  T old_value;
+};
+
 void GRExprEngine::EmitWarnings(Diagnostic& Diag, PathDiagnosticClient* PD) {
   for (bug_type_iterator I = bug_types_begin(), E = bug_types_end(); I!=E; ++I){
     BugReporter BR(Diag, PD, getContext(), *this);
@@ -140,6 +148,208 @@
   return StateMgr.SetRVal(St, Ex, V, isBlkExpr, false);
 }
 
+//===----------------------------------------------------------------------===//
+// Top-level transfer function logic (Dispatcher).
+//===----------------------------------------------------------------------===//
+
+void GRExprEngine::ProcessStmt(Stmt* S, StmtNodeBuilder& builder) {
+  
+  Builder = &builder;
+  StmtEntryNode = builder.getLastNode();
+  CurrentStmt = S;
+  NodeSet Dst;
+  
+  // Set up our simple checks.
+  
+  // FIXME: This can probably be installed directly in GRCoreEngine, obviating
+  //  the need to do a copy every time we hit a block-level statement.
+  
+  if (!MsgExprChecks.empty())
+    Builder->setObjCMsgExprAuditors((GRAuditor<ValueState>**) &MsgExprChecks[0],
+         (GRAuditor<ValueState>**) (&MsgExprChecks[0] + MsgExprChecks.size()));
+  
+  
+  if (!CallChecks.empty())
+    Builder->setCallExprAuditors((GRAuditor<ValueState>**) &CallChecks[0],
+         (GRAuditor<ValueState>**) (&CallChecks[0] + CallChecks.size()));
+  
+  // Create the cleaned state.
+  
+  CleanedState = StateMgr.RemoveDeadBindings(StmtEntryNode->getState(),
+                                             CurrentStmt, Liveness);
+  
+  Builder->SetCleanedState(CleanedState);
+  
+  // Visit the statement.
+  
+  Visit(S, StmtEntryNode, Dst);
+  
+  // If no nodes were generated, generate a new node that has all the
+  // dead mappings removed.
+  
+  if (Dst.size() == 1 && *Dst.begin() == StmtEntryNode)
+    builder.generateNode(S, GetState(StmtEntryNode), StmtEntryNode);
+  
+  // NULL out these variables to cleanup.
+  
+  CurrentStmt = NULL;
+  StmtEntryNode = NULL;
+  Builder = NULL;
+  CleanedState = NULL;
+}
+
+void GRExprEngine::Visit(Stmt* S, NodeTy* Pred, NodeSet& Dst) {
+  
+  // FIXME: add metadata to the CFG so that we can disable
+  //  this check when we KNOW that there is no block-level subexpression.
+  //  The motivation is that this check requires a hashtable lookup.
+  
+  if (S != CurrentStmt && getCFG().isBlkExpr(S)) {
+    Dst.Add(Pred);
+    return;
+  }
+  
+  switch (S->getStmtClass()) {
+      
+    default:
+      // Cases we intentionally have "default" handle:
+      //   AddrLabelExpr, IntegerLiteral, CharacterLiteral
+      
+      Dst.Add(Pred); // No-op. Simply propagate the current state unchanged.
+      break;
+      
+    case Stmt::AsmStmtClass:
+      VisitAsmStmt(cast<AsmStmt>(S), Pred, Dst);
+      break;
+      
+    case Stmt::BinaryOperatorClass: {
+      BinaryOperator* B = cast<BinaryOperator>(S);
+      
+      if (B->isLogicalOp()) {
+        VisitLogicalExpr(B, Pred, Dst);
+        break;
+      }
+      else if (B->getOpcode() == BinaryOperator::Comma) {
+        ValueState* St = GetState(Pred);
+        MakeNode(Dst, B, Pred, SetRVal(St, B, GetRVal(St, B->getRHS())));
+        break;
+      }
+      
+      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);
+      VisitCast(C, C->getSubExpr(), Pred, Dst);
+      break;
+    }
+      
+      // FIXME: ChooseExpr is really a constant.  We need to fix
+      //        the CFG do not model them as explicit control-flow.
+      
+    case Stmt::ChooseExprClass: { // __builtin_choose_expr
+      ChooseExpr* C = cast<ChooseExpr>(S);
+      VisitGuardedExpr(C, C->getLHS(), C->getRHS(), Pred, Dst);
+      break;
+    }
+      
+    case Stmt::CompoundAssignOperatorClass:
+      VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
+      break;
+      
+    case Stmt::ConditionalOperatorClass: { // '?' operator
+      ConditionalOperator* C = cast<ConditionalOperator>(S);
+      VisitGuardedExpr(C, C->getLHS(), C->getRHS(), Pred, Dst);
+      break;
+    }
+      
+    case Stmt::DeclRefExprClass:
+      VisitDeclRefExpr(cast<DeclRefExpr>(S), Pred, Dst);
+      break;
+      
+    case Stmt::DeclStmtClass:
+      VisitDeclStmt(cast<DeclStmt>(S), Pred, Dst);
+      break;
+      
+    case Stmt::ImplicitCastExprClass: {
+      ImplicitCastExpr* C = cast<ImplicitCastExpr>(S);
+      VisitCast(C, C->getSubExpr(), Pred, Dst);
+      break;
+    }
+      
+    case Stmt::ObjCMessageExprClass: {
+      VisitObjCMessageExpr(cast<ObjCMessageExpr>(S), Pred, Dst);
+      break;
+    }
+      
+    case Stmt::ParenExprClass:
+      Visit(cast<ParenExpr>(S)->getSubExpr(), Pred, Dst);
+      break;
+      
+    case Stmt::SizeOfAlignOfTypeExprClass:
+      VisitSizeOfAlignOfTypeExpr(cast<SizeOfAlignOfTypeExpr>(S), Pred, Dst);
+      break;
+      
+    case Stmt::StmtExprClass: {
+      StmtExpr* SE = cast<StmtExpr>(S);
+      
+      ValueState* St = GetState(Pred);
+      
+      // FIXME: Not certain if we can have empty StmtExprs.  If so, we should
+      // probably just remove these from the CFG.
+      assert (!SE->getSubStmt()->body_empty());
+      
+      if (Expr* LastExpr = dyn_cast<Expr>(*SE->getSubStmt()->body_rbegin()))
+        MakeNode(Dst, SE, Pred, SetRVal(St, SE, GetRVal(St, LastExpr)));
+      else
+        Dst.Add(Pred);
+      
+      break;
+    }
+      
+      // FIXME: We may wish to always bind state to ReturnStmts so
+      //  that users can quickly query what was the state at the
+      //  exit points of a function.
+      
+    case Stmt::ReturnStmtClass:
+      VisitReturnStmt(cast<ReturnStmt>(S), Pred, Dst); break;
+      
+    case Stmt::UnaryOperatorClass: {
+      UnaryOperator* U = cast<UnaryOperator>(S);
+      
+      switch (U->getOpcode()) {
+        case UnaryOperator::Deref: VisitDeref(U, Pred, Dst); break;
+        case UnaryOperator::Plus:  Visit(U->getSubExpr(), Pred, Dst); break;
+        case UnaryOperator::SizeOf: VisitSizeOfExpr(U, Pred, Dst); break;
+        default: VisitUnaryOperator(U, Pred, Dst); break;
+      }
+      
+      break;
+    }
+  }
+}
+
+//===----------------------------------------------------------------------===//
+// Block entrance.  (Update counters).
+//===----------------------------------------------------------------------===//
+
+bool GRExprEngine::ProcessBlockEntrance(CFGBlock* B, ValueState*,
+                                        GRBlockCounter BC) {
+  
+  return BC.getNumVisited(B->getBlockID()) < 3;
+}
+
+//===----------------------------------------------------------------------===//
+// Branch processing.
+//===----------------------------------------------------------------------===//
+
 ValueState* GRExprEngine::MarkBranch(ValueState* St, Stmt* Terminator,
                                      bool branchTaken) {
   
@@ -194,12 +404,6 @@
   }
 }
 
-bool GRExprEngine::ProcessBlockEntrance(CFGBlock* B, ValueState*,
-                                        GRBlockCounter BC) {
-  
-  return BC.getNumVisited(B->getBlockID()) < 3;
-}
-
 void GRExprEngine::ProcessBranch(Expr* Condition, Stmt* Term,
                                  BranchNodeBuilder& builder) {
 
@@ -236,7 +440,6 @@
     }      
   }
     
-
   // Process the true branch.
 
   bool isFeasible = false;  
@@ -303,6 +506,27 @@
     builder.generateNode(I, St);
 }
 
+
+void GRExprEngine::VisitGuardedExpr(Expr* Ex, Expr* L, Expr* R,
+                                    NodeTy* Pred, NodeSet& Dst) {
+  
+  assert (Ex == CurrentStmt && getCFG().isBlkExpr(Ex));
+  
+  ValueState* St = GetState(Pred);
+  RVal X = GetBlkExprRVal(St, Ex);
+  
+  assert (X.isUndef());
+  
+  Expr* SE = (Expr*) cast<UndefinedVal>(X).getData();
+  
+  assert (SE);
+  
+  X = GetBlkExprRVal(St, SE);
+  
+  // Make sure that we invalidate the previous binding.
+  MakeNode(Dst, Ex, Pred, StateMgr.SetRVal(St, Ex, X, true, true));
+}
+
 /// ProcessSwitch - Called by GRCoreEngine.  Used to generate successor
 ///  nodes by processing the 'effects' of a switch statement.
 void GRExprEngine::ProcessSwitch(SwitchNodeBuilder& builder) {
@@ -401,6 +625,9 @@
   builder.generateDefaultCaseNode(DefaultSt);
 }
 
+//===----------------------------------------------------------------------===//
+// Transfer functions: logical operations ('&&', '||').
+//===----------------------------------------------------------------------===//
 
 void GRExprEngine::VisitLogicalExpr(BinaryOperator* B, NodeTy* Pred,
                                     NodeSet& Dst) {
@@ -461,51 +688,9 @@
   }
 }
  
-
-void GRExprEngine::ProcessStmt(Stmt* S, StmtNodeBuilder& builder) {
-
-  Builder = &builder;
-  StmtEntryNode = builder.getLastNode();
-  CurrentStmt = S;
-  NodeSet Dst;
-  
-  // Set up our simple checks.
-  
-  if (!MsgExprChecks.empty())
-    Builder->setObjCMsgExprAuditors(
-      (GRAuditor<ValueState>**) &MsgExprChecks[0],
-      (GRAuditor<ValueState>**) (&MsgExprChecks[0] + MsgExprChecks.size()));
-
-  
-  if (!CallChecks.empty())
-    Builder->setCallExprAuditors(
-      (GRAuditor<ValueState>**) &CallChecks[0],
-      (GRAuditor<ValueState>**) (&CallChecks[0] + CallChecks.size()));
-  
-  // Create the cleaned state.
-
-  CleanedState = StateMgr.RemoveDeadBindings(StmtEntryNode->getState(),
-                                             CurrentStmt, Liveness);
-  
-  Builder->SetCleanedState(CleanedState);
-
-  // Visit the statement.
-
-  Visit(S, StmtEntryNode, Dst);
-
-  // If no nodes were generated, generate a new node that has all the
-  // dead mappings removed.
-  
-  if (Dst.size() == 1 && *Dst.begin() == StmtEntryNode)
-    builder.generateNode(S, GetState(StmtEntryNode), StmtEntryNode);
-  
-  // NULL out these variables to cleanup.
-  
-  CurrentStmt = NULL;
-  StmtEntryNode = NULL;
-  Builder = NULL;
-  CleanedState = NULL;
-}
+//===----------------------------------------------------------------------===//
+// Transfer functions: DeclRefExprs (loads, getting l-values).
+//===----------------------------------------------------------------------===//
 
 void GRExprEngine::VisitDeclRefExpr(DeclRefExpr* D, NodeTy* Pred, NodeSet& Dst){
 
@@ -523,6 +708,10 @@
   MakeNode(Dst, D, Pred, SetBlkExprRVal(St, D, Y));
 }
 
+//===----------------------------------------------------------------------===//
+// Transfer function: Function calls.
+//===----------------------------------------------------------------------===//
+
 void GRExprEngine::VisitCall(CallExpr* CE, NodeTy* Pred,
                              CallExpr::arg_iterator AI,
                              CallExpr::arg_iterator AE,
@@ -682,12 +871,120 @@
       
       EvalCall(Dst, CE, cast<LVal>(L), *DI);
       
-      if (!Builder->BuildSinks && Dst.size() == size)
-        MakeNode(Dst, CE, *DI, St);
-    }
-  }
+      // Handle the case where no nodes where generated.  Auto-generate that
+      // contains the updated state if we aren't generating sinks.
+      
+      if (!Builder->BuildSinks && Dst.size() == size)
+        MakeNode(Dst, CE, *DI, St);
+    }
+  }
+}
+
+//===----------------------------------------------------------------------===//
+// Transfer function: Objective-C message expressions.
+//===----------------------------------------------------------------------===//
+
+void GRExprEngine::VisitObjCMessageExpr(ObjCMessageExpr* ME, NodeTy* Pred,
+                                        NodeSet& Dst){
+  
+  VisitObjCMessageExprArgHelper(ME, ME->arg_begin(), ME->arg_end(),
+                                Pred, Dst);
+}  
+
+void GRExprEngine::VisitObjCMessageExprArgHelper(ObjCMessageExpr* ME,
+                                                 ObjCMessageExpr::arg_iterator AI,
+                                                 ObjCMessageExpr::arg_iterator AE,
+                                                 NodeTy* Pred, NodeSet& Dst) {
+  if (AI == AE) {
+    
+    // Process the receiver.
+    
+    if (Expr* Receiver = ME->getReceiver()) {
+      NodeSet Tmp;
+      Visit(Receiver, Pred, Tmp);
+      
+      for (NodeSet::iterator NI = Tmp.begin(), NE = Tmp.end(); NI != NE; ++NI)
+        VisitObjCMessageExprDispatchHelper(ME, *NI, Dst);
+      
+      return;
+    }
+    
+    VisitObjCMessageExprDispatchHelper(ME, Pred, Dst);
+    return;
+  }
+  
+  NodeSet Tmp;
+  Visit(*AI, Pred, Tmp);
+  
+  ++AI;
+  
+  for (NodeSet::iterator NI = Tmp.begin(), NE = Tmp.end(); NI != NE; ++NI)
+    VisitObjCMessageExprArgHelper(ME, AI, AE, *NI, Dst);
+}
+
+void GRExprEngine::VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME,
+                                                      NodeTy* Pred,
+                                                      NodeSet& Dst) {
+  
+  // FIXME: More logic for the processing the method call. 
+  
+  ValueState* St = GetState(Pred);
+  
+  if (Expr* Receiver = ME->getReceiver()) {
+    
+    RVal L = GetRVal(St, Receiver);
+    
+    // Check for undefined control-flow or calls to NULL.
+    
+    if (L.isUndef()) {
+      NodeTy* N = Builder->generateNode(ME, St, Pred);
+      
+      if (N) {
+        N->markAsSink();
+        UndefReceivers.insert(N);
+      }
+      
+      return;
+    }
+  }
+  
+  // Check for any arguments that are uninitialized/undefined.
+  
+  for (ObjCMessageExpr::arg_iterator I = ME->arg_begin(), E = ME->arg_end();
+       I != E; ++I) {
+    
+    if (GetRVal(St, *I).isUndef()) {
+      
+      // Generate an error node for passing an uninitialized/undefined value
+      // as an argument to a message expression.  This node is a sink.
+      NodeTy* N = Builder->generateNode(ME, St, Pred);
+      
+      if (N) {
+        N->markAsSink();
+        MsgExprUndefArgs[N] = *I;
+      }
+      
+      return;
+    }    
+  }    
+  // Dispatch to plug-in transfer function.
+  
+  unsigned size = Dst.size();
+  SaveAndRestore<bool> OldSink(Builder->BuildSinks);
+  
+  EvalObjCMessageExpr(Dst, ME, Pred);
+  
+  // Handle the case where no nodes where generated.  Auto-generate that
+  // contains the updated state if we aren't generating sinks.
+  
+  if (!Builder->BuildSinks && Dst.size() == size)
+    MakeNode(Dst, ME, Pred, St);
 }
 
+//===----------------------------------------------------------------------===//
+// Transfer functions: Miscellaneous statements.
+//===----------------------------------------------------------------------===//
+
 void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){
   
   NodeSet S1;
@@ -788,25 +1085,6 @@
 }
 
 
-void GRExprEngine::VisitGuardedExpr(Expr* Ex, Expr* L, Expr* R,
-                                   NodeTy* Pred, NodeSet& Dst) {
-  
-  assert (Ex == CurrentStmt && getCFG().isBlkExpr(Ex));
-
-  ValueState* St = GetState(Pred);
-  RVal X = GetBlkExprRVal(St, Ex);
-  
-  assert (X.isUndef());
-  
-  Expr* SE = (Expr*) cast<UndefinedVal>(X).getData();
-  
-  assert (SE);
-    
-  X = GetBlkExprRVal(St, SE);
-  
-  // Make sure that we invalidate the previous binding.
-  MakeNode(Dst, Ex, Pred, StateMgr.SetRVal(St, Ex, X, true, true));
-}
 
 /// VisitSizeOfAlignOfTypeExpr - Transfer function for sizeof(type).
 void GRExprEngine::VisitSizeOfAlignOfTypeExpr(SizeOfAlignOfTypeExpr* Ex,
@@ -1158,102 +1436,6 @@
     VisitAsmStmtHelperInputs(A, I, E, *NI, Dst);
 }
 
-
-void GRExprEngine::VisitObjCMessageExpr(ObjCMessageExpr* ME, NodeTy* Pred,
-                                        NodeSet& Dst){
-  VisitObjCMessageExprArgHelper(ME, ME->arg_begin(), ME->arg_end(), Pred, Dst);
-}  
-
-void GRExprEngine::VisitObjCMessageExprArgHelper(ObjCMessageExpr* ME,
-                                              ObjCMessageExpr::arg_iterator AI,
-                                              ObjCMessageExpr::arg_iterator AE,
-                                              NodeTy* Pred, NodeSet& Dst) {
-  if (AI == AE) {
-    
-    // Process the receiver.
-    
-    if (Expr* Receiver = ME->getReceiver()) {
-      NodeSet Tmp;
-      Visit(Receiver, Pred, Tmp);
-            
-      for (NodeSet::iterator NI = Tmp.begin(), NE = Tmp.end(); NI != NE; ++NI)
-        VisitObjCMessageExprDispatchHelper(ME, *NI, Dst);
-      
-      return;
-    }
-    
-    VisitObjCMessageExprDispatchHelper(ME, Pred, Dst);
-    return;
-  }
-  
-  NodeSet Tmp;
-  Visit(*AI, Pred, Tmp);
-  
-  ++AI;
-  
-  for (NodeSet::iterator NI = Tmp.begin(), NE = Tmp.end(); NI != NE; ++NI)
-    VisitObjCMessageExprArgHelper(ME, AI, AE, *NI, Dst);
-}
-
-void GRExprEngine::VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME,
-                                                 NodeTy* Pred, NodeSet& Dst) {
-  
-  
-  // FIXME: More logic for the processing the method call. 
-  
-  ValueState* St = GetState(Pred);
-  
-  if (Expr* Receiver = ME->getReceiver()) {
-  
-    RVal L = GetRVal(St, Receiver);
-    
-    // Check for undefined control-flow or calls to NULL.
-    
-    if (L.isUndef()) {
-      NodeTy* N = Builder->generateNode(ME, St, Pred);
-      
-      if (N) {
-        N->markAsSink();
-        UndefReceivers.insert(N);
-      }
-      
-      return;
-    }
-  }
-    
-  // Check for any arguments that are uninitialized/undefined.
-  
-  for (ObjCMessageExpr::arg_iterator I = ME->arg_begin(), E = ME->arg_end();
-       I != E; ++I) {
-    
-    if (GetRVal(St, *I).isUndef()) {
-      
-      NodeTy* N = Builder->generateNode(ME, St, Pred);
-      
-      if (N) {
-        N->markAsSink();
-        MsgExprUndefArgs[N] = *I;
-      }
-      
-      return;
-    }    
-  }
-  
-  // FIXME: Eventually we will properly handle the effects of a message
-  //  expr.  For now invalidate all arguments passed in by references.
-  
-  for (ObjCMessageExpr::arg_iterator I = ME->arg_begin(), E = ME->arg_end();
-       I != E; ++I) {
-    
-    RVal V = GetRVal(St, *I);
-    
-    if (isa<LVal>(V))
-      St = SetRVal(St, cast<LVal>(V), UnknownVal());
-  }
-  
-  MakeNode(Dst, ME, Pred, St);
-}
-
 void GRExprEngine::VisitReturnStmt(ReturnStmt* S, NodeTy* Pred, NodeSet& Dst) {
 
   Expr* R = S->getRetValue();
@@ -1299,6 +1481,10 @@
     Visit(R, Pred, Dst);
 }
 
+//===----------------------------------------------------------------------===//
+// Transfer functions: Binary operators.
+//===----------------------------------------------------------------------===//
+
 void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
                                        GRExprEngine::NodeTy* Pred,
                                        GRExprEngine::NodeSet& Dst) {
@@ -1613,143 +1799,6 @@
   UndefStores.insert(N);
 }
 
-void GRExprEngine::Visit(Stmt* S, NodeTy* Pred, NodeSet& Dst) {
-
-  // FIXME: add metadata to the CFG so that we can disable
-  //  this check when we KNOW that there is no block-level subexpression.
-  //  The motivation is that this check requires a hashtable lookup.
-
-  if (S != CurrentStmt && getCFG().isBlkExpr(S)) {
-    Dst.Add(Pred);
-    return;
-  }
-
-  switch (S->getStmtClass()) {
-      
-    default:
-      // Cases we intentionally have "default" handle:
-      //   AddrLabelExpr, IntegerLiteral, CharacterLiteral
-      
-      Dst.Add(Pred); // No-op. Simply propagate the current state unchanged.
-      break;
-      
-    case Stmt::AsmStmtClass:
-      VisitAsmStmt(cast<AsmStmt>(S), Pred, Dst);
-      break;
-                                                       
-    case Stmt::BinaryOperatorClass: {
-      BinaryOperator* B = cast<BinaryOperator>(S);
- 
-      if (B->isLogicalOp()) {
-        VisitLogicalExpr(B, Pred, Dst);
-        break;
-      }
-      else if (B->getOpcode() == BinaryOperator::Comma) {
-        ValueState* St = GetState(Pred);
-        MakeNode(Dst, B, Pred, SetRVal(St, B, GetRVal(St, B->getRHS())));
-        break;
-      }
-      
-      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);
-      VisitCast(C, C->getSubExpr(), Pred, Dst);
-      break;
-    }
-
-      // FIXME: ChooseExpr is really a constant.  We need to fix
-      //        the CFG do not model them as explicit control-flow.
-      
-    case Stmt::ChooseExprClass: { // __builtin_choose_expr
-      ChooseExpr* C = cast<ChooseExpr>(S);
-      VisitGuardedExpr(C, C->getLHS(), C->getRHS(), Pred, Dst);
-      break;
-    }
-      
-    case Stmt::CompoundAssignOperatorClass:
-      VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
-      break;
-      
-    case Stmt::ConditionalOperatorClass: { // '?' operator
-      ConditionalOperator* C = cast<ConditionalOperator>(S);
-      VisitGuardedExpr(C, C->getLHS(), C->getRHS(), Pred, Dst);
-      break;
-    }
-      
-    case Stmt::DeclRefExprClass:
-      VisitDeclRefExpr(cast<DeclRefExpr>(S), Pred, Dst);
-      break;
-      
-    case Stmt::DeclStmtClass:
-      VisitDeclStmt(cast<DeclStmt>(S), Pred, Dst);
-      break;
-      
-    case Stmt::ImplicitCastExprClass: {
-      ImplicitCastExpr* C = cast<ImplicitCastExpr>(S);
-      VisitCast(C, C->getSubExpr(), Pred, Dst);
-      break;
-    }
-      
-    case Stmt::ObjCMessageExprClass: {
-      VisitObjCMessageExpr(cast<ObjCMessageExpr>(S), Pred, Dst);
-      break;
-    }
-
-    case Stmt::ParenExprClass:
-      Visit(cast<ParenExpr>(S)->getSubExpr(), Pred, Dst);
-      break;
-      
-    case Stmt::SizeOfAlignOfTypeExprClass:
-      VisitSizeOfAlignOfTypeExpr(cast<SizeOfAlignOfTypeExpr>(S), Pred, Dst);
-      break;
-      
-    case Stmt::StmtExprClass: {
-      StmtExpr* SE = cast<StmtExpr>(S);
-      
-      ValueState* St = GetState(Pred);
-      
-      // FIXME: Not certain if we can have empty StmtExprs.  If so, we should
-      // probably just remove these from the CFG.
-      assert (!SE->getSubStmt()->body_empty());
-
-      if (Expr* LastExpr = dyn_cast<Expr>(*SE->getSubStmt()->body_rbegin()))
-        MakeNode(Dst, SE, Pred, SetRVal(St, SE, GetRVal(St, LastExpr)));
-      else
-        Dst.Add(Pred);
-      
-      break;
-    }
-      
-      // FIXME: We may wish to always bind state to ReturnStmts so
-      //  that users can quickly query what was the state at the
-      //  exit points of a function.
-      
-    case Stmt::ReturnStmtClass:
-      VisitReturnStmt(cast<ReturnStmt>(S), Pred, Dst); break;
-      
-    case Stmt::UnaryOperatorClass: {
-      UnaryOperator* U = cast<UnaryOperator>(S);
-      
-      switch (U->getOpcode()) {
-        case UnaryOperator::Deref: VisitDeref(U, Pred, Dst); break;
-        case UnaryOperator::Plus:  Visit(U->getSubExpr(), Pred, Dst); break;
-        case UnaryOperator::SizeOf: VisitSizeOfExpr(U, Pred, Dst); break;
-        default: VisitUnaryOperator(U, Pred, Dst); break;
-      }
-      
-      break;
-    }
-  }
-}
 
 //===----------------------------------------------------------------------===//
 // "Assume" logic.

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

==============================================================================
--- cfe/trunk/lib/Analysis/GRSimpleVals.cpp (original)
+++ cfe/trunk/lib/Analysis/GRSimpleVals.cpp Tue Apr 15 18:06:53 2008
@@ -552,7 +552,7 @@
 }
 
 //===----------------------------------------------------------------------===//
-// Transfer function for Function Calls.
+// Transfer function for function calls.
 //===----------------------------------------------------------------------===//
 
 void GRSimpleVals::EvalCall(ExplodedNodeSet<ValueState>& Dst,
@@ -590,3 +590,32 @@
     
   Builder.MakeNode(Dst, CE, Pred, St);
 }
+
+//===----------------------------------------------------------------------===//
+// Transfer function for Objective-C message expressions.
+//===----------------------------------------------------------------------===//
+
+void GRSimpleVals::EvalObjCMessageExpr(ExplodedNodeSet<ValueState>& Dst,
+                                       GRExprEngine& Eng,
+                                       GRStmtNodeBuilder<ValueState>& Builder,
+                                       ObjCMessageExpr* ME,
+                                       ExplodedNode<ValueState>* Pred) {
+  
+  
+  // The basic transfer function logic for message expressions does nothing.
+  // We just invalidate all arguments passed in by references.
+  
+  ValueStateManager& StateMgr = Eng.getStateManager();
+  ValueState* St = Builder.GetState(Pred);
+  
+  for (ObjCMessageExpr::arg_iterator I = ME->arg_begin(), E = ME->arg_end();
+       I != E; ++I) {
+    
+    RVal V = StateMgr.GetRVal(St, *I);
+    
+    if (isa<LVal>(V))
+      St = StateMgr.SetRVal(St, cast<LVal>(V), UnknownVal());
+  }
+  
+  Builder.MakeNode(Dst, ME, Pred, St);
+}

Modified: cfe/trunk/lib/Analysis/GRSimpleVals.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRSimpleVals.h?rev=49752&r1=49751&r2=49752&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/GRSimpleVals.h (original)
+++ cfe/trunk/lib/Analysis/GRSimpleVals.h Tue Apr 15 18:06:53 2008
@@ -63,6 +63,14 @@
                         CallExpr* CE, LVal L,
                         ExplodedNode<ValueState>* Pred);
   
+  virtual void EvalObjCMessageExpr(ExplodedNodeSet<ValueState>& Dst,
+                                   GRExprEngine& Engine,
+                                   GRStmtNodeBuilder<ValueState>& Builder,
+                                   ObjCMessageExpr* ME,
+                                   ExplodedNode<ValueState>* Pred);
+  
+  
+  
   static void GeneratePathDiagnostic(PathDiagnostic& PD, ASTContext& Ctx,
                                      ExplodedNode<ValueState>* N);
   





More information about the cfe-commits mailing list