[cfe-commits] r138194 - in /cfe/trunk/lib/StaticAnalyzer/Core: CMakeLists.txt ExprEngine.cpp ExprEngineC.cpp ExprEngineCallAndReturn.cpp ExprEngineObjC.cpp

Ted Kremenek kremenek at apple.com
Fri Aug 19 23:00:03 PDT 2011


Author: kremenek
Date: Sat Aug 20 01:00:03 2011
New Revision: 138194

URL: http://llvm.org/viewvc/llvm-project?rev=138194&view=rev
Log:
Start partitioning ExprEngine.cpp into separate .cpp files that handle different parts
of the analysis (e.g., analysis of C expressions, analysis of Objective-C expressions, and so on).

Added:
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
Modified:
    cfe/trunk/lib/StaticAnalyzer/Core/CMakeLists.txt
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Core/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/CMakeLists.txt?rev=138194&r1=138193&r2=138194&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/CMakeLists.txt (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/CMakeLists.txt Sat Aug 20 01:00:03 2011
@@ -20,7 +20,10 @@
   Environment.cpp
   ExplodedGraph.cpp
   ExprEngine.cpp
+  ExprEngineC.cpp
   ExprEngineCXX.cpp
+  ExprEngineCallAndReturn.cpp
+  ExprEngineObjC.cpp
   HTMLDiagnostics.cpp
   MemRegion.cpp
   ObjCMessage.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=138194&r1=138193&r2=138194&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Sat Aug 20 01:00:03 2011
@@ -37,15 +37,6 @@
 using namespace ento;
 using llvm::APSInt;
 
-namespace {
-  // Trait class for recording returned expression in the state.
-  struct ReturnExpr {
-    static int TagInt;
-    typedef const Stmt *data_type;
-  };
-  int ReturnExpr::TagInt; 
-}
-
 //===----------------------------------------------------------------------===//
 // Utility functions.
 //===----------------------------------------------------------------------===//
@@ -180,9 +171,12 @@
 
 /// evalAssume - Called by ConstraintManager. Used to call checker-specific
 ///  logic for handling assumptions on symbolic values.
-const ProgramState *ExprEngine::processAssume(const ProgramState *state, SVal cond,
-                                           bool assumption) {
-  state = getCheckerManager().runCheckersForEvalAssume(state, cond, assumption);
+const ProgramState *ExprEngine::processAssume(const ProgramState *state,
+                                              SVal cond,
+                                              bool assumption) {
+
+  state = getCheckerManager().runCheckersForEvalAssume(state, cond,
+                                                       assumption);
 
   // If the state is infeasible at this point, bail out.
   if (!state)
@@ -919,8 +913,10 @@
 /// integers that promote their values (which are currently not tracked well).
 /// This function returns the SVal bound to Condition->IgnoreCasts if all the
 //  cast(s) did was sign-extend the original value.
-static SVal RecoverCastedSymbol(ProgramStateManager& StateMgr, const ProgramState *state,
-                                const Stmt *Condition, ASTContext &Ctx) {
+static SVal RecoverCastedSymbol(ProgramStateManager& StateMgr,
+                                const ProgramState *state,
+                                const Stmt *Condition,
+                                ASTContext &Ctx) {
 
   const Expr *Ex = dyn_cast<Expr>(Condition);
   if (!Ex)
@@ -1064,27 +1060,6 @@
     builder.generateNode(I, state);
 }
 
-
-void ExprEngine::VisitGuardedExpr(const Expr *Ex, const Expr *L, 
-                                    const Expr *R,
-                                    ExplodedNode *Pred, ExplodedNodeSet &Dst) {
-
-  assert(Ex == currentStmt &&
-         Pred->getLocationContext()->getCFG()->isBlkExpr(Ex));
-
-  const ProgramState *state = Pred->getState();
-  SVal X = state->getSVal(Ex);
-
-  assert (X.isUndef());
-
-  const Expr *SE = (Expr*) cast<UndefinedVal>(X).getData();
-  assert(SE);
-  X = state->getSVal(SE);
-
-  // Make sure that we invalidate the previous binding.
-  MakeNode(Dst, Ex, Pred, state->BindExpr(Ex, X, true));
-}
-
 /// ProcessEndPath - Called by CoreEngine.  Used to generate end-of-path
 ///  nodes when the control reaches the end of a function.
 void ExprEngine::processEndOfFunction(EndOfFunctionNodeBuilder& builder) {
@@ -1208,114 +1183,10 @@
   builder.generateDefaultCaseNode(DefaultSt);
 }
 
-void ExprEngine::processCallEnter(CallEnterNodeBuilder &B) {
-  const ProgramState *state = B.getState()->enterStackFrame(B.getCalleeContext());
-  B.generateNode(state);
-}
-
-void ExprEngine::processCallExit(CallExitNodeBuilder &B) {
-  const ProgramState *state = B.getState();
-  const ExplodedNode *Pred = B.getPredecessor();
-  const StackFrameContext *calleeCtx = 
-                            cast<StackFrameContext>(Pred->getLocationContext());
-  const Stmt *CE = calleeCtx->getCallSite();
-
-  // If the callee returns an expression, bind its value to CallExpr.
-  const Stmt *ReturnedExpr = state->get<ReturnExpr>();
-  if (ReturnedExpr) {
-    SVal RetVal = state->getSVal(ReturnedExpr);
-    state = state->BindExpr(CE, RetVal);
-    // Clear the return expr GDM.
-    state = state->remove<ReturnExpr>();
-  }
-
-  // Bind the constructed object value to CXXConstructExpr.
-  if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(CE)) {
-    const CXXThisRegion *ThisR =
-      getCXXThisRegion(CCE->getConstructor()->getParent(), calleeCtx);
-
-    SVal ThisV = state->getSVal(ThisR);
-    // Always bind the region to the CXXConstructExpr.
-    state = state->BindExpr(CCE, ThisV);
-  }
-
-  B.generateNode(state);
-}
-
-//===----------------------------------------------------------------------===//
-// Transfer functions: logical operations ('&&', '||').
-//===----------------------------------------------------------------------===//
-
-void ExprEngine::VisitLogicalExpr(const BinaryOperator* B, ExplodedNode *Pred,
-                                    ExplodedNodeSet &Dst) {
-
-  assert(B->getOpcode() == BO_LAnd ||
-         B->getOpcode() == BO_LOr);
-
-  assert(B==currentStmt && Pred->getLocationContext()->getCFG()->isBlkExpr(B));
-
-  const ProgramState *state = Pred->getState();
-  SVal X = state->getSVal(B);
-  assert(X.isUndef());
-
-  const Expr *Ex = (const Expr*) cast<UndefinedVal>(X).getData();
-  assert(Ex);
-
-  if (Ex == B->getRHS()) {
-    X = state->getSVal(Ex);
-
-    // Handle undefined values.
-    if (X.isUndef()) {
-      MakeNode(Dst, B, Pred, state->BindExpr(B, X));
-      return;
-    }
-
-    DefinedOrUnknownSVal XD = cast<DefinedOrUnknownSVal>(X);
-
-    // We took the RHS.  Because the value of the '&&' or '||' expression must
-    // evaluate to 0 or 1, we must assume the value of the RHS evaluates to 0
-    // or 1.  Alternatively, we could take a lazy approach, and calculate this
-    // value later when necessary.  We don't have the machinery in place for
-    // this right now, and since most logical expressions are used for branches,
-    // the payoff is not likely to be large.  Instead, we do eager evaluation.
-    if (const ProgramState *newState = state->assume(XD, true))
-      MakeNode(Dst, B, Pred,
-               newState->BindExpr(B, svalBuilder.makeIntVal(1U, B->getType())));
-
-    if (const ProgramState *newState = state->assume(XD, false))
-      MakeNode(Dst, B, Pred,
-               newState->BindExpr(B, svalBuilder.makeIntVal(0U, B->getType())));
-  }
-  else {
-    // We took the LHS expression.  Depending on whether we are '&&' or
-    // '||' we know what the value of the expression is via properties of
-    // the short-circuiting.
-    X = svalBuilder.makeIntVal(B->getOpcode() == BO_LAnd ? 0U : 1U,
-                          B->getType());
-    MakeNode(Dst, B, Pred, state->BindExpr(B, X));
-  }
-}
-
 //===----------------------------------------------------------------------===//
 // Transfer functions: Loads and stores.
 //===----------------------------------------------------------------------===//
 
-void ExprEngine::VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred,
-                                  ExplodedNodeSet &Dst) {
-
-  ExplodedNodeSet Tmp;
-
-  CanQualType T = getContext().getCanonicalType(BE->getType());
-  SVal V = svalBuilder.getBlockPointer(BE->getBlockDecl(), T,
-                                  Pred->getLocationContext());
-
-  MakeNode(Tmp, BE, Pred, Pred->getState()->BindExpr(BE, V),
-           ProgramPoint::PostLValueKind);
-
-  // Post-visit the BlockExpr.
-  getCheckerManager().runCheckersForPostStmt(Dst, Tmp, BE, *this);
-}
-
 void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D,
                                         ExplodedNode *Pred,
                                         ExplodedNodeSet &Dst) {
@@ -1698,76 +1569,6 @@
 #endif
 }
 
-void ExprEngine::VisitCallExpr(const CallExpr *CE, ExplodedNode *Pred,
-                               ExplodedNodeSet &dst) {
-  // Perform the previsit of the CallExpr.
-  ExplodedNodeSet dstPreVisit;
-  getCheckerManager().runCheckersForPreStmt(dstPreVisit, Pred, CE, *this);
-    
-  // Now evaluate the call itself.
-  class DefaultEval : public GraphExpander {
-    ExprEngine &Eng;
-    const CallExpr *CE;
-  public:
-    
-    DefaultEval(ExprEngine &eng, const CallExpr *ce)
-      : Eng(eng), CE(ce) {}
-    virtual void expandGraph(ExplodedNodeSet &Dst, ExplodedNode *Pred) {
-      // Should we inline the call?
-      if (Eng.getAnalysisManager().shouldInlineCall() &&
-          Eng.InlineCall(Dst, CE, Pred)) {
-        return;
-      }
-
-      StmtNodeBuilder &Builder = Eng.getBuilder();
-      assert(&Builder && "StmtNodeBuilder must be defined.");
-
-      // Dispatch to the plug-in transfer function.
-      unsigned oldSize = Dst.size();
-      SaveOr OldHasGen(Builder.hasGeneratedNode);
-
-      // Dispatch to transfer function logic to handle the call itself.
-      const Expr *Callee = CE->getCallee()->IgnoreParens();
-      const ProgramState *state = Pred->getState();
-      SVal L = state->getSVal(Callee);
-      Eng.getTF().evalCall(Dst, Eng, Builder, CE, L, 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() == oldSize &&
-          !Builder.hasGeneratedNode)
-        Eng.MakeNode(Dst, CE, Pred, state);
-    }
-  };
-
-  // Finally, evaluate the function call.  We try each of the checkers
-  // to see if the can evaluate the function call.
-  ExplodedNodeSet dstCallEvaluated;
-  DefaultEval defEval(*this, CE);
-  getCheckerManager().runCheckersForEvalCall(dstCallEvaluated,
-                                             dstPreVisit,
-                                             CE, *this, &defEval);
-
-  // Finally, perform the post-condition check of the CallExpr and store
-  // the created nodes in 'Dst'.
-  getCheckerManager().runCheckersForPostStmt(dst, dstCallEvaluated, CE,
-                                             *this);
-}
-
-//===----------------------------------------------------------------------===//
-// Transfer function: Objective-C dot-syntax to access a property.
-//===----------------------------------------------------------------------===//
-
-void ExprEngine::VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *Ex,
-                                          ExplodedNode *Pred,
-                                          ExplodedNodeSet &Dst) {
-  MakeNode(Dst, Ex, Pred, Pred->getState()->BindExpr(Ex, loc::ObjCPropRef(Ex)));
-}
-
-//===----------------------------------------------------------------------===//
-// Transfer function: Objective-C ivar references.
-//===----------------------------------------------------------------------===//
-
 std::pair<const ProgramPointTag *, const ProgramPointTag*>
 ExprEngine::getEagerlyAssumeTags() {
   static SimpleProgramPointTag
@@ -1817,792 +1618,6 @@
   }
 }
 
-//===----------------------------------------------------------------------===//
-// Transfer function: Objective-C @synchronized.
-//===----------------------------------------------------------------------===//
-
-void ExprEngine::VisitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt *S,
-                                             ExplodedNode *Pred,
-                                             ExplodedNodeSet &Dst) {
-  getCheckerManager().runCheckersForPreStmt(Dst, Pred, S, *this);
-}
-
-//===----------------------------------------------------------------------===//
-// Transfer function: Objective-C ivar references.
-//===----------------------------------------------------------------------===//
-
-void ExprEngine::VisitLvalObjCIvarRefExpr(const ObjCIvarRefExpr *Ex, 
-                                          ExplodedNode *Pred,
-                                          ExplodedNodeSet &Dst) {
-
-  const ProgramState *state = Pred->getState();
-  SVal baseVal = state->getSVal(Ex->getBase());
-  SVal location = state->getLValue(Ex->getDecl(), baseVal);
-
-  ExplodedNodeSet dstIvar;
-  MakeNode(dstIvar, Ex, Pred, state->BindExpr(Ex, location));
-
-  // Perform the post-condition check of the ObjCIvarRefExpr and store
-  // the created nodes in 'Dst'.
-  getCheckerManager().runCheckersForPostStmt(Dst, dstIvar, Ex, *this);
-}
-
-//===----------------------------------------------------------------------===//
-// Transfer function: Objective-C fast enumeration 'for' statements.
-//===----------------------------------------------------------------------===//
-
-void ExprEngine::VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S,
-                                     ExplodedNode *Pred, ExplodedNodeSet &Dst) {
-
-  // ObjCForCollectionStmts are processed in two places.  This method
-  // handles the case where an ObjCForCollectionStmt* occurs as one of the
-  // statements within a basic block.  This transfer function does two things:
-  //
-  //  (1) binds the next container value to 'element'.  This creates a new
-  //      node in the ExplodedGraph.
-  //
-  //  (2) binds the value 0/1 to the ObjCForCollectionStmt* itself, indicating
-  //      whether or not the container has any more elements.  This value
-  //      will be tested in ProcessBranch.  We need to explicitly bind
-  //      this value because a container can contain nil elements.
-  //
-  // FIXME: Eventually this logic should actually do dispatches to
-  //   'countByEnumeratingWithState:objects:count:' (NSFastEnumeration).
-  //   This will require simulating a temporary NSFastEnumerationState, either
-  //   through an SVal or through the use of MemRegions.  This value can
-  //   be affixed to the ObjCForCollectionStmt* instead of 0/1; when the loop
-  //   terminates we reclaim the temporary (it goes out of scope) and we
-  //   we can test if the SVal is 0 or if the MemRegion is null (depending
-  //   on what approach we take).
-  //
-  //  For now: simulate (1) by assigning either a symbol or nil if the
-  //    container is empty.  Thus this transfer function will by default
-  //    result in state splitting.
-
-  const Stmt *elem = S->getElement();
-  const ProgramState *state = Pred->getState();
-  SVal elementV;
-
-  if (const DeclStmt *DS = dyn_cast<DeclStmt>(elem)) {
-    const VarDecl *elemD = cast<VarDecl>(DS->getSingleDecl());
-    assert(elemD->getInit() == 0);
-    elementV = state->getLValue(elemD, Pred->getLocationContext());
-  }
-  else {
-    elementV = state->getSVal(elem);
-  }
-  
-  ExplodedNodeSet dstLocation;
-  evalLocation(dstLocation, elem, Pred, state, elementV, NULL, false);
-
-  if (dstLocation.empty())
-    return;
-  
-  for (ExplodedNodeSet::iterator NI = dstLocation.begin(),
-                                 NE = dstLocation.end(); NI!=NE; ++NI) {
-    Pred = *NI;
-    const ProgramState *state = Pred->getState();
-    
-    // Handle the case where the container still has elements.
-    SVal TrueV = svalBuilder.makeTruthVal(1);
-    const ProgramState *hasElems = state->BindExpr(S, TrueV);
-    
-    // Handle the case where the container has no elements.
-    SVal FalseV = svalBuilder.makeTruthVal(0);
-    const ProgramState *noElems = state->BindExpr(S, FalseV);
-    
-    if (loc::MemRegionVal *MV = dyn_cast<loc::MemRegionVal>(&elementV))
-      if (const TypedValueRegion *R = 
-            dyn_cast<TypedValueRegion>(MV->getRegion())) {
-        // FIXME: The proper thing to do is to really iterate over the
-        //  container.  We will do this with dispatch logic to the store.
-        //  For now, just 'conjure' up a symbolic value.
-        QualType T = R->getValueType();
-        assert(Loc::isLocType(T));
-        unsigned Count = Builder->getCurrentBlockCount();
-        SymbolRef Sym = SymMgr.getConjuredSymbol(elem, T, Count);
-        SVal V = svalBuilder.makeLoc(Sym);
-        hasElems = hasElems->bindLoc(elementV, V);
-        
-        // Bind the location to 'nil' on the false branch.
-        SVal nilV = svalBuilder.makeIntVal(0, T);
-        noElems = noElems->bindLoc(elementV, nilV);
-      }
-    
-    // Create the new nodes.
-    MakeNode(Dst, S, Pred, hasElems);
-    MakeNode(Dst, S, Pred, noElems);
-  }
-}
-
-//===----------------------------------------------------------------------===//
-// Transfer function: Objective-C message expressions.
-//===----------------------------------------------------------------------===//
-
-void ExprEngine::VisitObjCMessage(const ObjCMessage &msg,
-                                  ExplodedNode *Pred, ExplodedNodeSet &Dst) {
-
-  // Handle the previsits checks.
-  ExplodedNodeSet dstPrevisit;
-  getCheckerManager().runCheckersForPreObjCMessage(dstPrevisit, Pred, 
-                                                   msg, *this);
-
-  // Proceed with evaluate the message expression.
-  ExplodedNodeSet dstEval;
-
-  for (ExplodedNodeSet::iterator DI = dstPrevisit.begin(),
-                                 DE = dstPrevisit.end(); DI != DE; ++DI) {
-
-    ExplodedNode *Pred = *DI;
-    bool RaisesException = false;
-    unsigned oldSize = dstEval.size();
-    SaveAndRestore<bool> OldSink(Builder->BuildSinks);
-    SaveOr OldHasGen(Builder->hasGeneratedNode);
-
-    if (const Expr *Receiver = msg.getInstanceReceiver()) {
-      const ProgramState *state = Pred->getState();
-      SVal recVal = state->getSVal(Receiver);
-      if (!recVal.isUndef()) {
-        // Bifurcate the state into nil and non-nil ones.
-        DefinedOrUnknownSVal receiverVal = cast<DefinedOrUnknownSVal>(recVal);
-    
-        const ProgramState *notNilState, *nilState;
-        llvm::tie(notNilState, nilState) = state->assume(receiverVal);
-    
-        // There are three cases: can be nil or non-nil, must be nil, must be
-        // non-nil. We ignore must be nil, and merge the rest two into non-nil.
-        if (nilState && !notNilState) {
-          dstEval.insert(Pred);
-          continue;
-        }
-    
-        // Check if the "raise" message was sent.
-        assert(notNilState);
-        if (msg.getSelector() == RaiseSel)
-          RaisesException = true;
-    
-        // Check if we raise an exception.  For now treat these as sinks.
-        // Eventually we will want to handle exceptions properly.
-        if (RaisesException)
-          Builder->BuildSinks = true;
-    
-        // Dispatch to plug-in transfer function.
-        evalObjCMessage(dstEval, msg, Pred, notNilState);
-      }
-    }
-    else if (const ObjCInterfaceDecl *Iface = msg.getReceiverInterface()) {
-      IdentifierInfo* ClsName = Iface->getIdentifier();
-      Selector S = msg.getSelector();
-
-      // Check for special instance methods.
-      if (!NSExceptionII) {
-        ASTContext &Ctx = getContext();
-        NSExceptionII = &Ctx.Idents.get("NSException");
-      }
-
-      if (ClsName == NSExceptionII) {
-        enum { NUM_RAISE_SELECTORS = 2 };
-
-        // Lazily create a cache of the selectors.
-        if (!NSExceptionInstanceRaiseSelectors) {
-          ASTContext &Ctx = getContext();
-          NSExceptionInstanceRaiseSelectors =
-            new Selector[NUM_RAISE_SELECTORS];
-          SmallVector<IdentifierInfo*, NUM_RAISE_SELECTORS> II;
-          unsigned idx = 0;
-
-          // raise:format:
-          II.push_back(&Ctx.Idents.get("raise"));
-          II.push_back(&Ctx.Idents.get("format"));
-          NSExceptionInstanceRaiseSelectors[idx++] =
-            Ctx.Selectors.getSelector(II.size(), &II[0]);
-
-          // raise:format::arguments:
-          II.push_back(&Ctx.Idents.get("arguments"));
-          NSExceptionInstanceRaiseSelectors[idx++] =
-            Ctx.Selectors.getSelector(II.size(), &II[0]);
-        }
-
-        for (unsigned i = 0; i < NUM_RAISE_SELECTORS; ++i)
-          if (S == NSExceptionInstanceRaiseSelectors[i]) {
-            RaisesException = true;
-            break;
-          }
-      }
-
-      // Check if we raise an exception.  For now treat these as sinks.
-      // Eventually we will want to handle exceptions properly.
-      if (RaisesException)
-        Builder->BuildSinks = true;
-
-      // Dispatch to plug-in transfer function.
-      evalObjCMessage(dstEval, msg, Pred, Pred->getState());
-    }
-
-    // Handle the case where no nodes where generated.  Auto-generate that
-    // contains the updated state if we aren't generating sinks.
-    if (!Builder->BuildSinks && dstEval.size() == oldSize &&
-        !Builder->hasGeneratedNode)
-      MakeNode(dstEval, msg.getOriginExpr(), Pred, Pred->getState());
-  }
-
-  // Finally, perform the post-condition check of the ObjCMessageExpr and store
-  // the created nodes in 'Dst'.
-  getCheckerManager().runCheckersForPostObjCMessage(Dst, dstEval, msg, *this);
-}
-
-//===----------------------------------------------------------------------===//
-// Transfer functions: Miscellaneous statements.
-//===----------------------------------------------------------------------===//
-
-void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex, 
-                           ExplodedNode *Pred, ExplodedNodeSet &Dst) {
-  
-  ExplodedNodeSet dstPreStmt;
-  getCheckerManager().runCheckersForPreStmt(dstPreStmt, Pred, CastE, *this);
-  
-  if (CastE->getCastKind() == CK_LValueToRValue ||
-      CastE->getCastKind() == CK_GetObjCProperty) {
-    for (ExplodedNodeSet::iterator I = dstPreStmt.begin(), E = dstPreStmt.end();
-         I!=E; ++I) {
-      ExplodedNode *subExprNode = *I;
-      const ProgramState *state = subExprNode->getState();
-      evalLoad(Dst, CastE, subExprNode, state, state->getSVal(Ex));
-    }
-    return;
-  }
-  
-  // All other casts.  
-  QualType T = CastE->getType();
-  QualType ExTy = Ex->getType();
-
-  if (const ExplicitCastExpr *ExCast=dyn_cast_or_null<ExplicitCastExpr>(CastE))
-    T = ExCast->getTypeAsWritten();
-
-  for (ExplodedNodeSet::iterator I = dstPreStmt.begin(), E = dstPreStmt.end();
-       I != E; ++I) {
-
-    Pred = *I;
-
-    switch (CastE->getCastKind()) {
-      case CK_LValueToRValue:
-        assert(false && "LValueToRValue casts handled earlier.");
-      case CK_GetObjCProperty:
-        assert(false && "GetObjCProperty casts handled earlier.");
-      case CK_ToVoid:
-        Dst.Add(Pred);
-        continue;
-      // The analyzer doesn't do anything special with these casts,
-      // since it understands retain/release semantics already.
-      case CK_ObjCProduceObject:
-      case CK_ObjCConsumeObject:
-      case CK_ObjCReclaimReturnedObject: // Fall-through.
-      // True no-ops.
-      case CK_NoOp:
-      case CK_FunctionToPointerDecay: {
-        // Copy the SVal of Ex to CastE.
-        const ProgramState *state = Pred->getState();
-        SVal V = state->getSVal(Ex);
-        state = state->BindExpr(CastE, V);
-        MakeNode(Dst, CastE, Pred, state);
-        continue;
-      }
-      case CK_Dependent:
-      case CK_ArrayToPointerDecay:
-      case CK_BitCast:
-      case CK_LValueBitCast:
-      case CK_IntegralCast:
-      case CK_NullToPointer:
-      case CK_IntegralToPointer:
-      case CK_PointerToIntegral:
-      case CK_PointerToBoolean:
-      case CK_IntegralToBoolean:
-      case CK_IntegralToFloating:
-      case CK_FloatingToIntegral:
-      case CK_FloatingToBoolean:
-      case CK_FloatingCast:
-      case CK_FloatingRealToComplex:
-      case CK_FloatingComplexToReal:
-      case CK_FloatingComplexToBoolean:
-      case CK_FloatingComplexCast:
-      case CK_FloatingComplexToIntegralComplex:
-      case CK_IntegralRealToComplex:
-      case CK_IntegralComplexToReal:
-      case CK_IntegralComplexToBoolean:
-      case CK_IntegralComplexCast:
-      case CK_IntegralComplexToFloatingComplex:
-      case CK_AnyPointerToObjCPointerCast:
-      case CK_AnyPointerToBlockPointerCast:  
-      case CK_ObjCObjectLValueCast: {
-        // Delegate to SValBuilder to process.
-        const ProgramState *state = Pred->getState();
-        SVal V = state->getSVal(Ex);
-        V = svalBuilder.evalCast(V, T, ExTy);
-        state = state->BindExpr(CastE, V);
-        MakeNode(Dst, CastE, Pred, state);
-        continue;
-      }
-      case CK_DerivedToBase:
-      case CK_UncheckedDerivedToBase: {
-        // For DerivedToBase cast, delegate to the store manager.
-        const ProgramState *state = Pred->getState();
-        SVal val = state->getSVal(Ex);
-        val = getStoreManager().evalDerivedToBase(val, T);
-        state = state->BindExpr(CastE, val);
-        MakeNode(Dst, CastE, Pred, state);
-        continue;
-      }
-      // Various C++ casts that are not handled yet.
-      case CK_Dynamic:
-      case CK_ToUnion:
-      case CK_BaseToDerived:
-      case CK_NullToMemberPointer:
-      case CK_BaseToDerivedMemberPointer:
-      case CK_DerivedToBaseMemberPointer:
-      case CK_UserDefinedConversion:
-      case CK_ConstructorConversion:
-      case CK_VectorSplat:
-      case CK_MemberPointerToBoolean: {
-        // Recover some path-sensitivty by conjuring a new value.
-        QualType resultType = CastE->getType();
-        if (CastE->isLValue())
-          resultType = getContext().getPointerType(resultType);
-
-        SVal result =
-          svalBuilder.getConjuredSymbolVal(NULL, CastE, resultType,
-                                           Builder->getCurrentBlockCount());
-
-        const ProgramState *state = Pred->getState()->BindExpr(CastE, result);
-        MakeNode(Dst, CastE, Pred, state);
-        continue;
-      }
-    }
-  }
-}
-
-void ExprEngine::VisitCompoundLiteralExpr(const CompoundLiteralExpr *CL,
-                                            ExplodedNode *Pred,
-                                            ExplodedNodeSet &Dst) {
-  const InitListExpr *ILE 
-    = cast<InitListExpr>(CL->getInitializer()->IgnoreParens());
-  
-  const ProgramState *state = Pred->getState();
-  SVal ILV = state->getSVal(ILE);
-
-  const LocationContext *LC = Pred->getLocationContext();
-  state = state->bindCompoundLiteral(CL, LC, ILV);
-
-  if (CL->isLValue()) {
-    MakeNode(Dst, CL, Pred, state->BindExpr(CL, state->getLValue(CL, LC)));
-  }
-  else
-    MakeNode(Dst, CL, Pred, state->BindExpr(CL, ILV));
-}
-
-void ExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred,
-                                 ExplodedNodeSet &Dst) {
-
-  // FIXME: static variables may have an initializer, but the second
-  //  time a function is called those values may not be current.
-  //  This may need to be reflected in the CFG.
-  
-  // Assumption: The CFG has one DeclStmt per Decl.
-  const Decl *D = *DS->decl_begin();
-
-  if (!D || !isa<VarDecl>(D))
-    return;
-
-
-  ExplodedNodeSet dstPreVisit;
-  getCheckerManager().runCheckersForPreStmt(dstPreVisit, Pred, DS, *this);
-
-  const VarDecl *VD = dyn_cast<VarDecl>(D);
-
-  for (ExplodedNodeSet::iterator I = dstPreVisit.begin(), E = dstPreVisit.end();
-       I!=E; ++I)
-  {
-    ExplodedNode *N = *I;
-    const ProgramState *state = N->getState();
-
-    // Decls without InitExpr are not initialized explicitly.
-    const LocationContext *LC = N->getLocationContext();
-
-    if (const Expr *InitEx = VD->getInit()) {
-      SVal InitVal = state->getSVal(InitEx);
-
-      // We bound the temp obj region to the CXXConstructExpr. Now recover
-      // the lazy compound value when the variable is not a reference.
-      if (AMgr.getLangOptions().CPlusPlus && VD->getType()->isRecordType() && 
-          !VD->getType()->isReferenceType() && isa<loc::MemRegionVal>(InitVal)){
-        InitVal = state->getSVal(cast<loc::MemRegionVal>(InitVal).getRegion());
-        assert(isa<nonloc::LazyCompoundVal>(InitVal));
-      }
-
-      // Recover some path-sensitivity if a scalar value evaluated to
-      // UnknownVal.
-      if ((InitVal.isUnknown() ||
-          !getConstraintManager().canReasonAbout(InitVal)) &&
-          !VD->getType()->isReferenceType()) {
-        InitVal = svalBuilder.getConjuredSymbolVal(NULL, InitEx,
-                                               Builder->getCurrentBlockCount());
-      }
-
-      evalBind(Dst, DS, N, state,
-               loc::MemRegionVal(state->getRegion(VD, LC)), InitVal, true);
-    }
-    else {
-      MakeNode(Dst, DS, N, state->bindDeclWithNoInit(state->getRegion(VD, LC)));
-    }
-  }
-}
-
-void ExprEngine::VisitInitListExpr(const InitListExpr *IE, ExplodedNode *Pred,
-                                    ExplodedNodeSet &Dst) {
-
-  const ProgramState *state = Pred->getState();
-  QualType T = getContext().getCanonicalType(IE->getType());
-  unsigned NumInitElements = IE->getNumInits();
-
-  if (T->isArrayType() || T->isRecordType() || T->isVectorType()) {
-    llvm::ImmutableList<SVal> vals = getBasicVals().getEmptySValList();
-
-    // Handle base case where the initializer has no elements.
-    // e.g: static int* myArray[] = {};
-    if (NumInitElements == 0) {
-      SVal V = svalBuilder.makeCompoundVal(T, vals);
-      MakeNode(Dst, IE, Pred, state->BindExpr(IE, V));
-      return;
-    }
-
-    for (InitListExpr::const_reverse_iterator it = IE->rbegin(),
-                                              ei = IE->rend(); it != ei; ++it) {
-      vals = getBasicVals().consVals(state->getSVal(cast<Expr>(*it)), vals);
-    }
-
-    MakeNode(Dst, IE, Pred,
-             state->BindExpr(IE, svalBuilder.makeCompoundVal(T, vals)));
-    return;
-  }
-
-  if (Loc::isLocType(T) || T->isIntegerType()) {
-    assert(IE->getNumInits() == 1);
-    const Expr *initEx = IE->getInit(0);
-    MakeNode(Dst, IE, Pred, state->BindExpr(IE, state->getSVal(initEx)));
-    return;
-  }
-
-  llvm_unreachable("unprocessed InitListExpr type");
-}
-
-/// VisitUnaryExprOrTypeTraitExpr - Transfer function for sizeof(type).
-void ExprEngine::VisitUnaryExprOrTypeTraitExpr(
-                                          const UnaryExprOrTypeTraitExpr *Ex,
-                                          ExplodedNode *Pred,
-                                          ExplodedNodeSet &Dst) {
-  QualType T = Ex->getTypeOfArgument();
-
-  if (Ex->getKind() == UETT_SizeOf) {
-    if (!T->isIncompleteType() && !T->isConstantSizeType()) {
-      assert(T->isVariableArrayType() && "Unknown non-constant-sized type.");
-
-      // FIXME: Add support for VLA type arguments, not just VLA expressions.
-      // When that happens, we should probably refactor VLASizeChecker's code.
-      if (Ex->isArgumentType()) {
-        Dst.Add(Pred);
-        return;
-      }
-
-      // Get the size by getting the extent of the sub-expression.
-      // First, visit the sub-expression to find its region.
-      const Expr *Arg = Ex->getArgumentExpr();
-      const ProgramState *state = Pred->getState();
-      const MemRegion *MR = state->getSVal(Arg).getAsRegion();
-
-      // If the subexpression can't be resolved to a region, we don't know
-      // anything about its size. Just leave the state as is and continue.
-      if (!MR) {
-        Dst.Add(Pred);
-        return;
-      }
-
-      // The result is the extent of the VLA.
-      SVal Extent = cast<SubRegion>(MR)->getExtent(svalBuilder);
-      MakeNode(Dst, Ex, Pred, state->BindExpr(Ex, Extent));
-
-      return;
-    }
-    else if (T->getAs<ObjCObjectType>()) {
-      // Some code tries to take the sizeof an ObjCObjectType, relying that
-      // the compiler has laid out its representation.  Just report Unknown
-      // for these.
-      Dst.Add(Pred);
-      return;
-    }
-  }
-
-  Expr::EvalResult Result;
-  Ex->Evaluate(Result, getContext());
-  CharUnits amt = CharUnits::fromQuantity(Result.Val.getInt().getZExtValue());
-
-  MakeNode(Dst, Ex, Pred,
-           Pred->getState()->BindExpr(Ex,
-              svalBuilder.makeIntVal(amt.getQuantity(), Ex->getType())));
-}
-
-void ExprEngine::VisitOffsetOfExpr(const OffsetOfExpr *OOE, 
-                                     ExplodedNode *Pred, ExplodedNodeSet &Dst) {
-  Expr::EvalResult Res;
-  if (OOE->Evaluate(Res, getContext()) && Res.Val.isInt()) {
-    const APSInt &IV = Res.Val.getInt();
-    assert(IV.getBitWidth() == getContext().getTypeSize(OOE->getType()));
-    assert(OOE->getType()->isIntegerType());
-    assert(IV.isSigned() == OOE->getType()->isSignedIntegerOrEnumerationType());
-    SVal X = svalBuilder.makeIntVal(IV);
-    MakeNode(Dst, OOE, Pred, Pred->getState()->BindExpr(OOE, X));
-    return;
-  }
-  // FIXME: Handle the case where __builtin_offsetof is not a constant.
-  Dst.Add(Pred);
-}
-
-void ExprEngine::VisitUnaryOperator(const UnaryOperator* U, 
-                                      ExplodedNode *Pred,
-                                      ExplodedNodeSet &Dst) {
-
-  switch (U->getOpcode()) {
-
-    default:
-      break;
-
-    case UO_Real: {
-      const Expr *Ex = U->getSubExpr()->IgnoreParens();
-      ExplodedNodeSet Tmp;
-      Visit(Ex, Pred, Tmp);
-
-      for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
-
-        // FIXME: We don't have complex SValues yet.
-        if (Ex->getType()->isAnyComplexType()) {
-          // Just report "Unknown."
-          Dst.Add(*I);
-          continue;
-        }
-
-        // For all other types, UO_Real is an identity operation.
-        assert (U->getType() == Ex->getType());
-        const ProgramState *state = (*I)->getState();
-        MakeNode(Dst, U, *I, state->BindExpr(U, state->getSVal(Ex)));
-      }
-
-      return;
-    }
-
-    case UO_Imag: {
-
-      const Expr *Ex = U->getSubExpr()->IgnoreParens();
-      ExplodedNodeSet Tmp;
-      Visit(Ex, Pred, Tmp);
-
-      for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
-        // FIXME: We don't have complex SValues yet.
-        if (Ex->getType()->isAnyComplexType()) {
-          // Just report "Unknown."
-          Dst.Add(*I);
-          continue;
-        }
-
-        // For all other types, UO_Imag returns 0.
-        const ProgramState *state = (*I)->getState();
-        SVal X = svalBuilder.makeZeroVal(Ex->getType());
-        MakeNode(Dst, U, *I, state->BindExpr(U, X));
-      }
-
-      return;
-    }
-      
-    case UO_Plus:
-      assert(!U->isLValue());
-      // FALL-THROUGH.
-    case UO_Deref:
-    case UO_AddrOf:
-    case UO_Extension: {
-
-      // Unary "+" is a no-op, similar to a parentheses.  We still have places
-      // where it may be a block-level expression, so we need to
-      // generate an extra node that just propagates the value of the
-      // subexpression.
-
-      const Expr *Ex = U->getSubExpr()->IgnoreParens();
-      ExplodedNodeSet Tmp;
-      Visit(Ex, Pred, Tmp);
-
-      for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
-        const ProgramState *state = (*I)->getState();
-        MakeNode(Dst, U, *I, state->BindExpr(U, state->getSVal(Ex)));
-      }
-
-      return;
-    }
-
-    case UO_LNot:
-    case UO_Minus:
-    case UO_Not: {
-      assert (!U->isLValue());
-      const Expr *Ex = U->getSubExpr()->IgnoreParens();
-      ExplodedNodeSet Tmp;
-      Visit(Ex, Pred, Tmp);
-
-      for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
-        const ProgramState *state = (*I)->getState();
-
-        // Get the value of the subexpression.
-        SVal V = state->getSVal(Ex);
-
-        if (V.isUnknownOrUndef()) {
-          MakeNode(Dst, U, *I, state->BindExpr(U, V));
-          continue;
-        }
-
-//        QualType DstT = getContext().getCanonicalType(U->getType());
-//        QualType SrcT = getContext().getCanonicalType(Ex->getType());
-//
-//        if (DstT != SrcT) // Perform promotions.
-//          V = evalCast(V, DstT);
-//
-//        if (V.isUnknownOrUndef()) {
-//          MakeNode(Dst, U, *I, BindExpr(St, U, V));
-//          continue;
-//        }
-
-        switch (U->getOpcode()) {
-          default:
-            assert(false && "Invalid Opcode.");
-            break;
-
-          case UO_Not:
-            // FIXME: Do we need to handle promotions?
-            state = state->BindExpr(U, evalComplement(cast<NonLoc>(V)));
-            break;
-
-          case UO_Minus:
-            // FIXME: Do we need to handle promotions?
-            state = state->BindExpr(U, evalMinus(cast<NonLoc>(V)));
-            break;
-
-          case UO_LNot:
-
-            // C99 6.5.3.3: "The expression !E is equivalent to (0==E)."
-            //
-            //  Note: technically we do "E == 0", but this is the same in the
-            //    transfer functions as "0 == E".
-            SVal Result;
-
-            if (isa<Loc>(V)) {
-              Loc X = svalBuilder.makeNull();
-              Result = evalBinOp(state, BO_EQ, cast<Loc>(V), X,
-                                 U->getType());
-            }
-            else {
-              nonloc::ConcreteInt X(getBasicVals().getValue(0, Ex->getType()));
-              Result = evalBinOp(state, BO_EQ, cast<NonLoc>(V), X,
-                                 U->getType());
-            }
-
-            state = state->BindExpr(U, Result);
-
-            break;
-        }
-
-        MakeNode(Dst, U, *I, state);
-      }
-
-      return;
-    }
-  }
-
-  // Handle ++ and -- (both pre- and post-increment).
-  assert (U->isIncrementDecrementOp());
-  ExplodedNodeSet Tmp;
-  const Expr *Ex = U->getSubExpr()->IgnoreParens();
-  Visit(Ex, Pred, Tmp);
-
-  for (ExplodedNodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I!=E; ++I) {
-
-    const ProgramState *state = (*I)->getState();
-    SVal loc = state->getSVal(Ex);
-
-    // Perform a load.
-    ExplodedNodeSet Tmp2;
-    evalLoad(Tmp2, Ex, *I, state, loc);
-
-    for (ExplodedNodeSet::iterator I2=Tmp2.begin(), E2=Tmp2.end();I2!=E2;++I2) {
-
-      state = (*I2)->getState();
-      SVal V2_untested = state->getSVal(Ex);
-
-      // Propagate unknown and undefined values.
-      if (V2_untested.isUnknownOrUndef()) {
-        MakeNode(Dst, U, *I2, state->BindExpr(U, V2_untested));
-        continue;
-      }
-      DefinedSVal V2 = cast<DefinedSVal>(V2_untested);
-
-      // Handle all other values.
-      BinaryOperator::Opcode Op = U->isIncrementOp() ? BO_Add
-                                                     : BO_Sub;
-
-      // If the UnaryOperator has non-location type, use its type to create the
-      // constant value. If the UnaryOperator has location type, create the
-      // constant with int type and pointer width.
-      SVal RHS;
-
-      if (U->getType()->isAnyPointerType())
-        RHS = svalBuilder.makeArrayIndex(1);
-      else
-        RHS = svalBuilder.makeIntVal(1, U->getType());
-
-      SVal Result = evalBinOp(state, Op, V2, RHS, U->getType());
-
-      // Conjure a new symbol if necessary to recover precision.
-      if (Result.isUnknown() || !getConstraintManager().canReasonAbout(Result)){
-        DefinedOrUnknownSVal SymVal =
-          svalBuilder.getConjuredSymbolVal(NULL, Ex,
-                                      Builder->getCurrentBlockCount());
-        Result = SymVal;
-
-        // If the value is a location, ++/-- should always preserve
-        // non-nullness.  Check if the original value was non-null, and if so
-        // propagate that constraint.
-        if (Loc::isLocType(U->getType())) {
-          DefinedOrUnknownSVal Constraint =
-            svalBuilder.evalEQ(state, V2,svalBuilder.makeZeroVal(U->getType()));
-
-          if (!state->assume(Constraint, true)) {
-            // It isn't feasible for the original value to be null.
-            // Propagate this constraint.
-            Constraint = svalBuilder.evalEQ(state, SymVal,
-                                       svalBuilder.makeZeroVal(U->getType()));
-
-
-            state = state->assume(Constraint, false);
-            assert(state);
-          }
-        }
-      }
-
-      // Since the lvalue-to-rvalue conversion is explicit in the AST,
-      // we bind an l-value if the operator is prefix and an lvalue (in C++).
-      if (U->isLValue())
-        state = state->BindExpr(U, loc);
-      else
-        state = state->BindExpr(U, U->isPostfix() ? V2 : Result);
-
-      // Perform the store.
-      evalStore(Dst, NULL, U, *I2, state, loc, Result);
-    }
-  }
-}
-
 void ExprEngine::VisitAsmStmt(const AsmStmt *A, ExplodedNode *Pred,
                                 ExplodedNodeSet &Dst) {
   VisitAsmStmtHelperOutputs(A, A->begin_outputs(), A->end_outputs(), Pred, Dst);
@@ -2664,198 +1679,6 @@
     VisitAsmStmtHelperInputs(A, I, E, *NI, Dst);
 }
 
-void ExprEngine::VisitReturnStmt(const ReturnStmt *RS, ExplodedNode *Pred,
-                                   ExplodedNodeSet &Dst) {
-  ExplodedNodeSet Src;
-  if (const Expr *RetE = RS->getRetValue()) {
-    // Record the returned expression in the state. It will be used in
-    // processCallExit to bind the return value to the call expr.
-    {
-      static SimpleProgramPointTag tag("ExprEngine: ReturnStmt");
-      const ProgramState *state = Pred->getState();
-      state = state->set<ReturnExpr>(RetE);
-      Pred = Builder->generateNode(RetE, state, Pred, &tag);
-    }
-    // We may get a NULL Pred because we generated a cached node.
-    if (Pred)
-      Visit(RetE, Pred, Src);
-  }
-  else {
-    Src.Add(Pred);
-  }
-
-  ExplodedNodeSet CheckedSet;
-  getCheckerManager().runCheckersForPreStmt(CheckedSet, Src, RS, *this);
-
-  for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end();
-       I != E; ++I) {
-
-    assert(Builder && "StmtNodeBuilder must be defined.");
-
-    Pred = *I;
-    unsigned size = Dst.size();
-
-    SaveAndRestore<bool> OldSink(Builder->BuildSinks);
-    SaveOr OldHasGen(Builder->hasGeneratedNode);
-
-    getTF().evalReturn(Dst, *this, *Builder, RS, Pred);
-
-    // Handle the case where no nodes where generated.
-    if (!Builder->BuildSinks && Dst.size() == size &&
-        !Builder->hasGeneratedNode)
-      MakeNode(Dst, RS, Pred, Pred->getState());
-  }
-}
-
-//===----------------------------------------------------------------------===//
-// Transfer functions: Binary operators.
-//===----------------------------------------------------------------------===//
-
-void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
-                                       ExplodedNode *Pred,
-                                       ExplodedNodeSet &Dst) {
-  ExplodedNodeSet Tmp1;
-  Expr *LHS = B->getLHS()->IgnoreParens();
-  Expr *RHS = B->getRHS()->IgnoreParens();
-
-  Visit(LHS, Pred, Tmp1);
-  ExplodedNodeSet Tmp3;
-
-  for (ExplodedNodeSet::iterator I1=Tmp1.begin(), E1=Tmp1.end(); I1!=E1; ++I1) {
-    SVal LeftV = (*I1)->getState()->getSVal(LHS);
-    ExplodedNodeSet Tmp2;
-    Visit(RHS, *I1, Tmp2);
-
-    ExplodedNodeSet CheckedSet;
-    getCheckerManager().runCheckersForPreStmt(CheckedSet, Tmp2, B, *this);
-
-    // With both the LHS and RHS evaluated, process the operation itself.
-
-    for (ExplodedNodeSet::iterator I2=CheckedSet.begin(), E2=CheckedSet.end();
-         I2 != E2; ++I2) {
-
-      const ProgramState *state = (*I2)->getState();
-      SVal RightV = state->getSVal(RHS);
-
-      BinaryOperator::Opcode Op = B->getOpcode();
-
-      if (Op == BO_Assign) {
-        // EXPERIMENTAL: "Conjured" symbols.
-        // FIXME: Handle structs.
-        if (RightV.isUnknown() ||!getConstraintManager().canReasonAbout(RightV))
-        {
-          unsigned Count = Builder->getCurrentBlockCount();
-          RightV = svalBuilder.getConjuredSymbolVal(NULL, B->getRHS(), Count);
-        }
-
-        SVal ExprVal = B->isLValue() ? LeftV : RightV;
-
-        // Simulate the effects of a "store":  bind the value of the RHS
-        // to the L-Value represented by the LHS.
-        evalStore(Tmp3, B, LHS, *I2, state->BindExpr(B, ExprVal), LeftV,RightV);
-        continue;
-      }
-
-      if (!B->isAssignmentOp()) {
-        // Process non-assignments except commas or short-circuited
-        // logical expressions (LAnd and LOr).
-        SVal Result = evalBinOp(state, Op, LeftV, RightV, B->getType());
-
-        if (Result.isUnknown()) {
-          MakeNode(Tmp3, B, *I2, state);
-          continue;
-        }
-
-        state = state->BindExpr(B, Result);
-
-        MakeNode(Tmp3, B, *I2, state);
-        continue;
-      }
-
-      assert (B->isCompoundAssignmentOp());
-
-      switch (Op) {
-        default:
-          assert(0 && "Invalid opcode for compound assignment.");
-        case BO_MulAssign: Op = BO_Mul; break;
-        case BO_DivAssign: Op = BO_Div; break;
-        case BO_RemAssign: Op = BO_Rem; break;
-        case BO_AddAssign: Op = BO_Add; break;
-        case BO_SubAssign: Op = BO_Sub; break;
-        case BO_ShlAssign: Op = BO_Shl; break;
-        case BO_ShrAssign: Op = BO_Shr; break;
-        case BO_AndAssign: Op = BO_And; break;
-        case BO_XorAssign: Op = BO_Xor; break;
-        case BO_OrAssign:  Op = BO_Or;  break;
-      }
-
-      // Perform a load (the LHS).  This performs the checks for
-      // null dereferences, and so on.
-      ExplodedNodeSet Tmp4;
-      SVal location = state->getSVal(LHS);
-      evalLoad(Tmp4, LHS, *I2, state, location);
-
-      for (ExplodedNodeSet::iterator I4=Tmp4.begin(), E4=Tmp4.end(); I4!=E4;
-           ++I4) {
-        state = (*I4)->getState();
-        SVal V = state->getSVal(LHS);
-
-        // Get the computation type.
-        QualType CTy =
-          cast<CompoundAssignOperator>(B)->getComputationResultType();
-        CTy = getContext().getCanonicalType(CTy);
-
-        QualType CLHSTy =
-          cast<CompoundAssignOperator>(B)->getComputationLHSType();
-        CLHSTy = getContext().getCanonicalType(CLHSTy);
-
-        QualType LTy = getContext().getCanonicalType(LHS->getType());
-
-        // Promote LHS.
-        V = svalBuilder.evalCast(V, CLHSTy, LTy);
-
-        // Compute the result of the operation.
-        SVal Result = svalBuilder.evalCast(evalBinOp(state, Op, V, RightV, CTy),
-                                      B->getType(), CTy);
-
-        // EXPERIMENTAL: "Conjured" symbols.
-        // FIXME: Handle structs.
-
-        SVal LHSVal;
-
-        if (Result.isUnknown() ||
-            !getConstraintManager().canReasonAbout(Result)) {
-
-          unsigned Count = Builder->getCurrentBlockCount();
-
-          // The symbolic value is actually for the type of the left-hand side
-          // expression, not the computation type, as this is the value the
-          // LValue on the LHS will bind to.
-          LHSVal = svalBuilder.getConjuredSymbolVal(NULL, B->getRHS(), LTy, Count);
-
-          // However, we need to convert the symbol to the computation type.
-          Result = svalBuilder.evalCast(LHSVal, CTy, LTy);
-        }
-        else {
-          // The left-hand side may bind to a different value then the
-          // computation type.
-          LHSVal = svalBuilder.evalCast(Result, LTy, CTy);
-        }
-
-        // In C++, assignment and compound assignment operators return an 
-        // lvalue.
-        if (B->isLValue())
-          state = state->BindExpr(B, location);
-        else
-          state = state->BindExpr(B, Result);
-
-        evalStore(Tmp3, B, LHS, *I4, state, location, LHSVal);
-      }
-    }
-  }
-
-  getCheckerManager().runCheckersForPostStmt(Dst, Tmp3, B, *this);
-}
 
 //===----------------------------------------------------------------------===//
 // Visualization.

Added: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp?rev=138194&view=auto
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp (added)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp Sat Aug 20 01:00:03 2011
@@ -0,0 +1,781 @@
+//=-- ExprEngineC.cpp - ExprEngine support for C expressions ----*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file defines ExprEngine's support for C expressions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+#include "clang/Analysis/Support/SaveAndRestore.h"
+
+using namespace clang;
+using namespace ento;
+using llvm::APSInt;
+
+void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
+                                     ExplodedNode *Pred,
+                                     ExplodedNodeSet &Dst) {
+  ExplodedNodeSet Tmp1;
+  Expr *LHS = B->getLHS()->IgnoreParens();
+  Expr *RHS = B->getRHS()->IgnoreParens();
+  
+  Visit(LHS, Pred, Tmp1);
+  ExplodedNodeSet Tmp3;
+  
+  for (ExplodedNodeSet::iterator I1=Tmp1.begin(), E1=Tmp1.end(); I1!=E1; ++I1) {
+    SVal LeftV = (*I1)->getState()->getSVal(LHS);
+    ExplodedNodeSet Tmp2;
+    Visit(RHS, *I1, Tmp2);
+    
+    ExplodedNodeSet CheckedSet;
+    getCheckerManager().runCheckersForPreStmt(CheckedSet, Tmp2, B, *this);
+    
+    // With both the LHS and RHS evaluated, process the operation itself.
+    
+    for (ExplodedNodeSet::iterator I2=CheckedSet.begin(), E2=CheckedSet.end();
+         I2 != E2; ++I2) {
+      
+      const ProgramState *state = (*I2)->getState();
+      SVal RightV = state->getSVal(RHS);
+      
+      BinaryOperator::Opcode Op = B->getOpcode();
+      
+      if (Op == BO_Assign) {
+        // EXPERIMENTAL: "Conjured" symbols.
+        // FIXME: Handle structs.
+        if (RightV.isUnknown() ||!getConstraintManager().canReasonAbout(RightV))
+        {
+          unsigned Count = Builder->getCurrentBlockCount();
+          RightV = svalBuilder.getConjuredSymbolVal(NULL, B->getRHS(), Count);
+        }
+        
+        SVal ExprVal = B->isLValue() ? LeftV : RightV;
+        
+        // Simulate the effects of a "store":  bind the value of the RHS
+        // to the L-Value represented by the LHS.
+        evalStore(Tmp3, B, LHS, *I2, state->BindExpr(B, ExprVal), LeftV,RightV);
+        continue;
+      }
+      
+      if (!B->isAssignmentOp()) {
+        // Process non-assignments except commas or short-circuited
+        // logical expressions (LAnd and LOr).
+        SVal Result = evalBinOp(state, Op, LeftV, RightV, B->getType());
+        
+        if (Result.isUnknown()) {
+          MakeNode(Tmp3, B, *I2, state);
+          continue;
+        }
+        
+        state = state->BindExpr(B, Result);
+        
+        MakeNode(Tmp3, B, *I2, state);
+        continue;
+      }
+      
+      assert (B->isCompoundAssignmentOp());
+      
+      switch (Op) {
+        default:
+          assert(0 && "Invalid opcode for compound assignment.");
+        case BO_MulAssign: Op = BO_Mul; break;
+        case BO_DivAssign: Op = BO_Div; break;
+        case BO_RemAssign: Op = BO_Rem; break;
+        case BO_AddAssign: Op = BO_Add; break;
+        case BO_SubAssign: Op = BO_Sub; break;
+        case BO_ShlAssign: Op = BO_Shl; break;
+        case BO_ShrAssign: Op = BO_Shr; break;
+        case BO_AndAssign: Op = BO_And; break;
+        case BO_XorAssign: Op = BO_Xor; break;
+        case BO_OrAssign:  Op = BO_Or;  break;
+      }
+      
+      // Perform a load (the LHS).  This performs the checks for
+      // null dereferences, and so on.
+      ExplodedNodeSet Tmp4;
+      SVal location = state->getSVal(LHS);
+      evalLoad(Tmp4, LHS, *I2, state, location);
+      
+      for (ExplodedNodeSet::iterator I4=Tmp4.begin(), E4=Tmp4.end(); I4!=E4;
+           ++I4) {
+        state = (*I4)->getState();
+        SVal V = state->getSVal(LHS);
+        
+        // Get the computation type.
+        QualType CTy =
+        cast<CompoundAssignOperator>(B)->getComputationResultType();
+        CTy = getContext().getCanonicalType(CTy);
+        
+        QualType CLHSTy =
+        cast<CompoundAssignOperator>(B)->getComputationLHSType();
+        CLHSTy = getContext().getCanonicalType(CLHSTy);
+        
+        QualType LTy = getContext().getCanonicalType(LHS->getType());
+        
+        // Promote LHS.
+        V = svalBuilder.evalCast(V, CLHSTy, LTy);
+        
+        // Compute the result of the operation.
+        SVal Result = svalBuilder.evalCast(evalBinOp(state, Op, V, RightV, CTy),
+                                           B->getType(), CTy);
+        
+        // EXPERIMENTAL: "Conjured" symbols.
+        // FIXME: Handle structs.
+        
+        SVal LHSVal;
+        
+        if (Result.isUnknown() ||
+            !getConstraintManager().canReasonAbout(Result)) {
+          
+          unsigned Count = Builder->getCurrentBlockCount();
+          
+          // The symbolic value is actually for the type of the left-hand side
+          // expression, not the computation type, as this is the value the
+          // LValue on the LHS will bind to.
+          LHSVal = svalBuilder.getConjuredSymbolVal(NULL, B->getRHS(), LTy, Count);
+          
+          // However, we need to convert the symbol to the computation type.
+          Result = svalBuilder.evalCast(LHSVal, CTy, LTy);
+        }
+        else {
+          // The left-hand side may bind to a different value then the
+          // computation type.
+          LHSVal = svalBuilder.evalCast(Result, LTy, CTy);
+        }
+        
+        // In C++, assignment and compound assignment operators return an 
+        // lvalue.
+        if (B->isLValue())
+          state = state->BindExpr(B, location);
+        else
+          state = state->BindExpr(B, Result);
+        
+        evalStore(Tmp3, B, LHS, *I4, state, location, LHSVal);
+      }
+    }
+  }
+  
+  getCheckerManager().runCheckersForPostStmt(Dst, Tmp3, B, *this);
+}
+
+void ExprEngine::VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred,
+                                ExplodedNodeSet &Dst) {
+  
+  CanQualType T = getContext().getCanonicalType(BE->getType());
+  SVal V = svalBuilder.getBlockPointer(BE->getBlockDecl(), T,
+                                       Pred->getLocationContext());
+  
+  ExplodedNodeSet Tmp;
+  MakeNode(Tmp, BE, Pred, Pred->getState()->BindExpr(BE, V),
+           ProgramPoint::PostLValueKind);
+  
+  // FIXME: Move all post/pre visits to ::Visit().
+  getCheckerManager().runCheckersForPostStmt(Dst, Tmp, BE, *this);
+}
+
+void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex, 
+                           ExplodedNode *Pred, ExplodedNodeSet &Dst) {
+  
+  ExplodedNodeSet dstPreStmt;
+  getCheckerManager().runCheckersForPreStmt(dstPreStmt, Pred, CastE, *this);
+  
+  if (CastE->getCastKind() == CK_LValueToRValue ||
+      CastE->getCastKind() == CK_GetObjCProperty) {
+    for (ExplodedNodeSet::iterator I = dstPreStmt.begin(), E = dstPreStmt.end();
+         I!=E; ++I) {
+      ExplodedNode *subExprNode = *I;
+      const ProgramState *state = subExprNode->getState();
+      evalLoad(Dst, CastE, subExprNode, state, state->getSVal(Ex));
+    }
+    return;
+  }
+  
+  // All other casts.  
+  QualType T = CastE->getType();
+  QualType ExTy = Ex->getType();
+  
+  if (const ExplicitCastExpr *ExCast=dyn_cast_or_null<ExplicitCastExpr>(CastE))
+    T = ExCast->getTypeAsWritten();
+  
+  for (ExplodedNodeSet::iterator I = dstPreStmt.begin(), E = dstPreStmt.end();
+       I != E; ++I) {
+    
+    Pred = *I;
+    
+    switch (CastE->getCastKind()) {
+      case CK_LValueToRValue:
+        assert(false && "LValueToRValue casts handled earlier.");
+      case CK_GetObjCProperty:
+        assert(false && "GetObjCProperty casts handled earlier.");
+      case CK_ToVoid:
+        Dst.Add(Pred);
+        continue;
+        // The analyzer doesn't do anything special with these casts,
+        // since it understands retain/release semantics already.
+      case CK_ObjCProduceObject:
+      case CK_ObjCConsumeObject:
+      case CK_ObjCReclaimReturnedObject: // Fall-through.
+        // True no-ops.
+      case CK_NoOp:
+      case CK_FunctionToPointerDecay: {
+        // Copy the SVal of Ex to CastE.
+        const ProgramState *state = Pred->getState();
+        SVal V = state->getSVal(Ex);
+        state = state->BindExpr(CastE, V);
+        MakeNode(Dst, CastE, Pred, state);
+        continue;
+      }
+      case CK_Dependent:
+      case CK_ArrayToPointerDecay:
+      case CK_BitCast:
+      case CK_LValueBitCast:
+      case CK_IntegralCast:
+      case CK_NullToPointer:
+      case CK_IntegralToPointer:
+      case CK_PointerToIntegral:
+      case CK_PointerToBoolean:
+      case CK_IntegralToBoolean:
+      case CK_IntegralToFloating:
+      case CK_FloatingToIntegral:
+      case CK_FloatingToBoolean:
+      case CK_FloatingCast:
+      case CK_FloatingRealToComplex:
+      case CK_FloatingComplexToReal:
+      case CK_FloatingComplexToBoolean:
+      case CK_FloatingComplexCast:
+      case CK_FloatingComplexToIntegralComplex:
+      case CK_IntegralRealToComplex:
+      case CK_IntegralComplexToReal:
+      case CK_IntegralComplexToBoolean:
+      case CK_IntegralComplexCast:
+      case CK_IntegralComplexToFloatingComplex:
+      case CK_AnyPointerToObjCPointerCast:
+      case CK_AnyPointerToBlockPointerCast:  
+      case CK_ObjCObjectLValueCast: {
+        // Delegate to SValBuilder to process.
+        const ProgramState *state = Pred->getState();
+        SVal V = state->getSVal(Ex);
+        V = svalBuilder.evalCast(V, T, ExTy);
+        state = state->BindExpr(CastE, V);
+        MakeNode(Dst, CastE, Pred, state);
+        continue;
+      }
+      case CK_DerivedToBase:
+      case CK_UncheckedDerivedToBase: {
+        // For DerivedToBase cast, delegate to the store manager.
+        const ProgramState *state = Pred->getState();
+        SVal val = state->getSVal(Ex);
+        val = getStoreManager().evalDerivedToBase(val, T);
+        state = state->BindExpr(CastE, val);
+        MakeNode(Dst, CastE, Pred, state);
+        continue;
+      }
+        // Various C++ casts that are not handled yet.
+      case CK_Dynamic:
+      case CK_ToUnion:
+      case CK_BaseToDerived:
+      case CK_NullToMemberPointer:
+      case CK_BaseToDerivedMemberPointer:
+      case CK_DerivedToBaseMemberPointer:
+      case CK_UserDefinedConversion:
+      case CK_ConstructorConversion:
+      case CK_VectorSplat:
+      case CK_MemberPointerToBoolean: {
+        // Recover some path-sensitivty by conjuring a new value.
+        QualType resultType = CastE->getType();
+        if (CastE->isLValue())
+          resultType = getContext().getPointerType(resultType);
+        
+        SVal result =
+        svalBuilder.getConjuredSymbolVal(NULL, CastE, resultType,
+                                         Builder->getCurrentBlockCount());
+        
+        const ProgramState *state = Pred->getState()->BindExpr(CastE, result);
+        MakeNode(Dst, CastE, Pred, state);
+        continue;
+      }
+    }
+  }
+}
+
+void ExprEngine::VisitCompoundLiteralExpr(const CompoundLiteralExpr *CL,
+                                          ExplodedNode *Pred,
+                                          ExplodedNodeSet &Dst) {
+  const InitListExpr *ILE 
+    = cast<InitListExpr>(CL->getInitializer()->IgnoreParens());
+  
+  const ProgramState *state = Pred->getState();
+  SVal ILV = state->getSVal(ILE);
+  const LocationContext *LC = Pred->getLocationContext();
+  state = state->bindCompoundLiteral(CL, LC, ILV);
+  
+  if (CL->isLValue())
+    MakeNode(Dst, CL, Pred, state->BindExpr(CL, state->getLValue(CL, LC)));
+  else
+    MakeNode(Dst, CL, Pred, state->BindExpr(CL, ILV));
+}
+
+void ExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred,
+                               ExplodedNodeSet &Dst) {
+  
+  // FIXME: static variables may have an initializer, but the second
+  //  time a function is called those values may not be current.
+  //  This may need to be reflected in the CFG.
+  
+  // Assumption: The CFG has one DeclStmt per Decl.
+  const Decl *D = *DS->decl_begin();
+  
+  if (!D || !isa<VarDecl>(D))
+    return;
+  
+  // FIXME: all pre/post visits should eventually be handled by ::Visit().
+  ExplodedNodeSet dstPreVisit;
+  getCheckerManager().runCheckersForPreStmt(dstPreVisit, Pred, DS, *this);
+  
+  const VarDecl *VD = dyn_cast<VarDecl>(D);
+  
+  for (ExplodedNodeSet::iterator I = dstPreVisit.begin(), E = dstPreVisit.end();
+       I!=E; ++I) {
+    ExplodedNode *N = *I;
+    const ProgramState *state = N->getState();
+    
+    // Decls without InitExpr are not initialized explicitly.
+    const LocationContext *LC = N->getLocationContext();
+    
+    if (const Expr *InitEx = VD->getInit()) {
+      SVal InitVal = state->getSVal(InitEx);
+      
+      // We bound the temp obj region to the CXXConstructExpr. Now recover
+      // the lazy compound value when the variable is not a reference.
+      if (AMgr.getLangOptions().CPlusPlus && VD->getType()->isRecordType() && 
+          !VD->getType()->isReferenceType() && isa<loc::MemRegionVal>(InitVal)){
+        InitVal = state->getSVal(cast<loc::MemRegionVal>(InitVal).getRegion());
+        assert(isa<nonloc::LazyCompoundVal>(InitVal));
+      }
+      
+      // Recover some path-sensitivity if a scalar value evaluated to
+      // UnknownVal.
+      if ((InitVal.isUnknown() ||
+           !getConstraintManager().canReasonAbout(InitVal)) &&
+          !VD->getType()->isReferenceType()) {
+        InitVal = svalBuilder.getConjuredSymbolVal(NULL, InitEx,
+                                                   Builder->getCurrentBlockCount());
+      }
+      
+      evalBind(Dst, DS, N, state,
+               loc::MemRegionVal(state->getRegion(VD, LC)), InitVal, true);
+    }
+    else {
+      MakeNode(Dst, DS, N, state->bindDeclWithNoInit(state->getRegion(VD, LC)));
+    }
+  }
+}
+
+void ExprEngine::VisitLogicalExpr(const BinaryOperator* B, ExplodedNode *Pred,
+                                  ExplodedNodeSet &Dst) {
+  
+  assert(B->getOpcode() == BO_LAnd ||
+         B->getOpcode() == BO_LOr);
+  
+  const ProgramState *state = Pred->getState();
+  SVal X = state->getSVal(B);
+  assert(X.isUndef());
+  
+  const Expr *Ex = (const Expr*) cast<UndefinedVal>(X).getData();
+  assert(Ex);
+  
+  if (Ex == B->getRHS()) {
+    X = state->getSVal(Ex);
+    
+    // Handle undefined values.
+    if (X.isUndef()) {
+      MakeNode(Dst, B, Pred, state->BindExpr(B, X));
+      return;
+    }
+    
+    DefinedOrUnknownSVal XD = cast<DefinedOrUnknownSVal>(X);
+    
+    // We took the RHS.  Because the value of the '&&' or '||' expression must
+    // evaluate to 0 or 1, we must assume the value of the RHS evaluates to 0
+    // or 1.  Alternatively, we could take a lazy approach, and calculate this
+    // value later when necessary.  We don't have the machinery in place for
+    // this right now, and since most logical expressions are used for branches,
+    // the payoff is not likely to be large.  Instead, we do eager evaluation.
+    if (const ProgramState *newState = state->assume(XD, true))
+      MakeNode(Dst, B, Pred,
+               newState->BindExpr(B, svalBuilder.makeIntVal(1U, B->getType())));
+    
+    if (const ProgramState *newState = state->assume(XD, false))
+      MakeNode(Dst, B, Pred,
+               newState->BindExpr(B, svalBuilder.makeIntVal(0U, B->getType())));
+  }
+  else {
+    // We took the LHS expression.  Depending on whether we are '&&' or
+    // '||' we know what the value of the expression is via properties of
+    // the short-circuiting.
+    X = svalBuilder.makeIntVal(B->getOpcode() == BO_LAnd ? 0U : 1U,
+                               B->getType());
+    MakeNode(Dst, B, Pred, state->BindExpr(B, X));
+  }
+}
+
+void ExprEngine::VisitInitListExpr(const InitListExpr *IE,
+                                   ExplodedNode *Pred,
+                                   ExplodedNodeSet &Dst) {
+
+  const ProgramState *state = Pred->getState();
+  QualType T = getContext().getCanonicalType(IE->getType());
+  unsigned NumInitElements = IE->getNumInits();
+  
+  if (T->isArrayType() || T->isRecordType() || T->isVectorType()) {
+    llvm::ImmutableList<SVal> vals = getBasicVals().getEmptySValList();
+    
+    // Handle base case where the initializer has no elements.
+    // e.g: static int* myArray[] = {};
+    if (NumInitElements == 0) {
+      SVal V = svalBuilder.makeCompoundVal(T, vals);
+      MakeNode(Dst, IE, Pred, state->BindExpr(IE, V));
+      return;
+    }
+    
+    for (InitListExpr::const_reverse_iterator it = IE->rbegin(),
+         ei = IE->rend(); it != ei; ++it) {
+      vals = getBasicVals().consVals(state->getSVal(cast<Expr>(*it)), vals);
+    }
+    
+    MakeNode(Dst, IE, Pred,
+             state->BindExpr(IE, svalBuilder.makeCompoundVal(T, vals)));
+    return;
+  }
+  
+  if (Loc::isLocType(T) || T->isIntegerType()) {
+    assert(IE->getNumInits() == 1);
+    const Expr *initEx = IE->getInit(0);
+    MakeNode(Dst, IE, Pred, state->BindExpr(IE, state->getSVal(initEx)));
+    return;
+  }
+  
+  llvm_unreachable("unprocessed InitListExpr type");
+}
+
+void ExprEngine::VisitGuardedExpr(const Expr *Ex,
+                                  const Expr *L, 
+                                  const Expr *R,
+                                  ExplodedNode *Pred,
+                                  ExplodedNodeSet &Dst) {
+  
+  const ProgramState *state = Pred->getState();
+  SVal X = state->getSVal(Ex);  
+  assert (X.isUndef());  
+  const Expr *SE = (Expr*) cast<UndefinedVal>(X).getData();
+  assert(SE);
+  X = state->getSVal(SE);
+  
+  // Make sure that we invalidate the previous binding.
+  MakeNode(Dst, Ex, Pred, state->BindExpr(Ex, X, true));
+}
+
+void ExprEngine::
+VisitOffsetOfExpr(const OffsetOfExpr *OOE, 
+                  ExplodedNode *Pred, ExplodedNodeSet &Dst) {
+  Expr::EvalResult Res;
+  if (OOE->Evaluate(Res, getContext()) && Res.Val.isInt()) {
+    const APSInt &IV = Res.Val.getInt();
+    assert(IV.getBitWidth() == getContext().getTypeSize(OOE->getType()));
+    assert(OOE->getType()->isIntegerType());
+    assert(IV.isSigned() == OOE->getType()->isSignedIntegerOrEnumerationType());
+    SVal X = svalBuilder.makeIntVal(IV);
+    MakeNode(Dst, OOE, Pred, Pred->getState()->BindExpr(OOE, X));
+    return;
+  }
+  // FIXME: Handle the case where __builtin_offsetof is not a constant.
+  Dst.Add(Pred);
+}
+
+
+void ExprEngine::
+VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Ex,
+                              ExplodedNode *Pred,
+                              ExplodedNodeSet &Dst) {
+
+  QualType T = Ex->getTypeOfArgument();
+  
+  if (Ex->getKind() == UETT_SizeOf) {
+    if (!T->isIncompleteType() && !T->isConstantSizeType()) {
+      assert(T->isVariableArrayType() && "Unknown non-constant-sized type.");
+      
+      // FIXME: Add support for VLA type arguments, not just VLA expressions.
+      // When that happens, we should probably refactor VLASizeChecker's code.
+      if (Ex->isArgumentType()) {
+        Dst.Add(Pred);
+        return;
+      }
+      
+      // Get the size by getting the extent of the sub-expression.
+      // First, visit the sub-expression to find its region.
+      const Expr *Arg = Ex->getArgumentExpr();
+      const ProgramState *state = Pred->getState();
+      const MemRegion *MR = state->getSVal(Arg).getAsRegion();
+      
+      // If the subexpression can't be resolved to a region, we don't know
+      // anything about its size. Just leave the state as is and continue.
+      if (!MR) {
+        Dst.Add(Pred);
+        return;
+      }
+      
+      // The result is the extent of the VLA.
+      SVal Extent = cast<SubRegion>(MR)->getExtent(svalBuilder);
+      MakeNode(Dst, Ex, Pred, state->BindExpr(Ex, Extent));
+      
+      return;
+    }
+    else if (T->getAs<ObjCObjectType>()) {
+      // Some code tries to take the sizeof an ObjCObjectType, relying that
+      // the compiler has laid out its representation.  Just report Unknown
+      // for these.
+      Dst.Add(Pred);
+      return;
+    }
+  }
+  
+  Expr::EvalResult Result;
+  Ex->Evaluate(Result, getContext());
+  CharUnits amt = CharUnits::fromQuantity(Result.Val.getInt().getZExtValue());
+  
+  const ProgramState *state = Pred->getState();
+  state = state->BindExpr(Ex, svalBuilder.makeIntVal(amt.getQuantity(),
+                                                     Ex->getType()));
+  MakeNode(Dst, Ex, Pred, state);
+}
+
+void ExprEngine::VisitUnaryOperator(const UnaryOperator* U, 
+                                    ExplodedNode *Pred,
+                                    ExplodedNodeSet &Dst) {  
+  switch (U->getOpcode()) {
+    default:
+      break;
+    case UO_Real: {
+      const Expr *Ex = U->getSubExpr()->IgnoreParens();
+      ExplodedNodeSet Tmp;
+      Visit(Ex, Pred, Tmp);
+      
+      for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
+        
+        // FIXME: We don't have complex SValues yet.
+        if (Ex->getType()->isAnyComplexType()) {
+          // Just report "Unknown."
+          Dst.Add(*I);
+          continue;
+        }
+        
+        // For all other types, UO_Real is an identity operation.
+        assert (U->getType() == Ex->getType());
+        const ProgramState *state = (*I)->getState();
+        MakeNode(Dst, U, *I, state->BindExpr(U, state->getSVal(Ex)));
+      }
+      
+      return;
+    }
+      
+    case UO_Imag: {
+      
+      const Expr *Ex = U->getSubExpr()->IgnoreParens();
+      ExplodedNodeSet Tmp;
+      Visit(Ex, Pred, Tmp);
+      
+      for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
+        // FIXME: We don't have complex SValues yet.
+        if (Ex->getType()->isAnyComplexType()) {
+          // Just report "Unknown."
+          Dst.Add(*I);
+          continue;
+        }
+        
+        // For all other types, UO_Imag returns 0.
+        const ProgramState *state = (*I)->getState();
+        SVal X = svalBuilder.makeZeroVal(Ex->getType());
+        MakeNode(Dst, U, *I, state->BindExpr(U, X));
+      }
+      
+      return;
+    }
+      
+    case UO_Plus:
+      assert(!U->isLValue());
+      // FALL-THROUGH.
+    case UO_Deref:
+    case UO_AddrOf:
+    case UO_Extension: {
+      
+      // Unary "+" is a no-op, similar to a parentheses.  We still have places
+      // where it may be a block-level expression, so we need to
+      // generate an extra node that just propagates the value of the
+      // subexpression.
+      
+      const Expr *Ex = U->getSubExpr()->IgnoreParens();
+      ExplodedNodeSet Tmp;
+      Visit(Ex, Pred, Tmp);
+      
+      for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
+        const ProgramState *state = (*I)->getState();
+        MakeNode(Dst, U, *I, state->BindExpr(U, state->getSVal(Ex)));
+      }
+      
+      return;
+    }
+      
+    case UO_LNot:
+    case UO_Minus:
+    case UO_Not: {
+      assert (!U->isLValue());
+      const Expr *Ex = U->getSubExpr()->IgnoreParens();
+      ExplodedNodeSet Tmp;
+      Visit(Ex, Pred, Tmp);
+      
+      for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
+        const ProgramState *state = (*I)->getState();
+        
+        // Get the value of the subexpression.
+        SVal V = state->getSVal(Ex);
+        
+        if (V.isUnknownOrUndef()) {
+          MakeNode(Dst, U, *I, state->BindExpr(U, V));
+          continue;
+        }
+        
+        switch (U->getOpcode()) {
+          default:
+            assert(false && "Invalid Opcode.");
+            break;
+            
+          case UO_Not:
+            // FIXME: Do we need to handle promotions?
+            state = state->BindExpr(U, evalComplement(cast<NonLoc>(V)));
+            break;
+            
+          case UO_Minus:
+            // FIXME: Do we need to handle promotions?
+            state = state->BindExpr(U, evalMinus(cast<NonLoc>(V)));
+            break;
+            
+          case UO_LNot:
+            
+            // C99 6.5.3.3: "The expression !E is equivalent to (0==E)."
+            //
+            //  Note: technically we do "E == 0", but this is the same in the
+            //    transfer functions as "0 == E".
+            SVal Result;
+            
+            if (isa<Loc>(V)) {
+              Loc X = svalBuilder.makeNull();
+              Result = evalBinOp(state, BO_EQ, cast<Loc>(V), X,
+                                 U->getType());
+            }
+            else {
+              nonloc::ConcreteInt X(getBasicVals().getValue(0, Ex->getType()));
+              Result = evalBinOp(state, BO_EQ, cast<NonLoc>(V), X,
+                                 U->getType());
+            }
+            
+            state = state->BindExpr(U, Result);
+            
+            break;
+        }
+        
+        MakeNode(Dst, U, *I, state);
+      }
+      
+      return;
+    }
+  }
+  
+  // Handle ++ and -- (both pre- and post-increment).
+  assert (U->isIncrementDecrementOp());
+  ExplodedNodeSet Tmp;
+  const Expr *Ex = U->getSubExpr()->IgnoreParens();
+  Visit(Ex, Pred, Tmp);
+  
+  for (ExplodedNodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I!=E; ++I) {
+    
+    const ProgramState *state = (*I)->getState();
+    SVal loc = state->getSVal(Ex);
+    
+    // Perform a load.
+    ExplodedNodeSet Tmp2;
+    evalLoad(Tmp2, Ex, *I, state, loc);
+    
+    for (ExplodedNodeSet::iterator I2=Tmp2.begin(), E2=Tmp2.end();I2!=E2;++I2) {
+      
+      state = (*I2)->getState();
+      SVal V2_untested = state->getSVal(Ex);
+      
+      // Propagate unknown and undefined values.
+      if (V2_untested.isUnknownOrUndef()) {
+        MakeNode(Dst, U, *I2, state->BindExpr(U, V2_untested));
+        continue;
+      }
+      DefinedSVal V2 = cast<DefinedSVal>(V2_untested);
+      
+      // Handle all other values.
+      BinaryOperator::Opcode Op = U->isIncrementOp() ? BO_Add
+      : BO_Sub;
+      
+      // If the UnaryOperator has non-location type, use its type to create the
+      // constant value. If the UnaryOperator has location type, create the
+      // constant with int type and pointer width.
+      SVal RHS;
+      
+      if (U->getType()->isAnyPointerType())
+        RHS = svalBuilder.makeArrayIndex(1);
+      else
+        RHS = svalBuilder.makeIntVal(1, U->getType());
+      
+      SVal Result = evalBinOp(state, Op, V2, RHS, U->getType());
+      
+      // Conjure a new symbol if necessary to recover precision.
+      if (Result.isUnknown() || !getConstraintManager().canReasonAbout(Result)){
+        DefinedOrUnknownSVal SymVal =
+        svalBuilder.getConjuredSymbolVal(NULL, Ex,
+                                         Builder->getCurrentBlockCount());
+        Result = SymVal;
+        
+        // If the value is a location, ++/-- should always preserve
+        // non-nullness.  Check if the original value was non-null, and if so
+        // propagate that constraint.
+        if (Loc::isLocType(U->getType())) {
+          DefinedOrUnknownSVal Constraint =
+          svalBuilder.evalEQ(state, V2,svalBuilder.makeZeroVal(U->getType()));
+          
+          if (!state->assume(Constraint, true)) {
+            // It isn't feasible for the original value to be null.
+            // Propagate this constraint.
+            Constraint = svalBuilder.evalEQ(state, SymVal,
+                                            svalBuilder.makeZeroVal(U->getType()));
+            
+            
+            state = state->assume(Constraint, false);
+            assert(state);
+          }
+        }
+      }
+      
+      // Since the lvalue-to-rvalue conversion is explicit in the AST,
+      // we bind an l-value if the operator is prefix and an lvalue (in C++).
+      if (U->isLValue())
+        state = state->BindExpr(U, loc);
+      else
+        state = state->BindExpr(U, U->isPostfix() ? V2 : Result);
+      
+      // Perform the store.
+      evalStore(Dst, NULL, U, *I2, state, loc, Result);
+    }
+  }
+}

Added: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp?rev=138194&view=auto
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp (added)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp Sat Aug 20 01:00:03 2011
@@ -0,0 +1,163 @@
+//=-- ExprEngineCallAndReturn.cpp - Support for call/return -----*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file defines ExprEngine's support for calls and returns.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/Analysis/Support/SaveAndRestore.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+  // Trait class for recording returned expression in the state.
+  struct ReturnExpr {
+    static int TagInt;
+    typedef const Stmt *data_type;
+  };
+  int ReturnExpr::TagInt; 
+}
+
+void ExprEngine::processCallEnter(CallEnterNodeBuilder &B) {
+  const ProgramState *state =
+    B.getState()->enterStackFrame(B.getCalleeContext());
+  B.generateNode(state);
+}
+
+void ExprEngine::processCallExit(CallExitNodeBuilder &B) {
+  const ProgramState *state = B.getState();
+  const ExplodedNode *Pred = B.getPredecessor();
+  const StackFrameContext *calleeCtx = 
+    cast<StackFrameContext>(Pred->getLocationContext());
+  const Stmt *CE = calleeCtx->getCallSite();
+  
+  // If the callee returns an expression, bind its value to CallExpr.
+  const Stmt *ReturnedExpr = state->get<ReturnExpr>();
+  if (ReturnedExpr) {
+    SVal RetVal = state->getSVal(ReturnedExpr);
+    state = state->BindExpr(CE, RetVal);
+    // Clear the return expr GDM.
+    state = state->remove<ReturnExpr>();
+  }
+  
+  // Bind the constructed object value to CXXConstructExpr.
+  if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(CE)) {
+    const CXXThisRegion *ThisR =
+    getCXXThisRegion(CCE->getConstructor()->getParent(), calleeCtx);
+    
+    SVal ThisV = state->getSVal(ThisR);
+    // Always bind the region to the CXXConstructExpr.
+    state = state->BindExpr(CCE, ThisV);
+  }
+  
+  B.generateNode(state);
+}
+
+void ExprEngine::VisitCallExpr(const CallExpr *CE, ExplodedNode *Pred,
+                               ExplodedNodeSet &dst) {
+  // Perform the previsit of the CallExpr.
+  ExplodedNodeSet dstPreVisit;
+  getCheckerManager().runCheckersForPreStmt(dstPreVisit, Pred, CE, *this);
+  
+  // Now evaluate the call itself.
+  class DefaultEval : public GraphExpander {
+    ExprEngine &Eng;
+    const CallExpr *CE;
+  public:
+    
+    DefaultEval(ExprEngine &eng, const CallExpr *ce)
+    : Eng(eng), CE(ce) {}
+    virtual void expandGraph(ExplodedNodeSet &Dst, ExplodedNode *Pred) {
+      // Should we inline the call?
+      if (Eng.getAnalysisManager().shouldInlineCall() &&
+          Eng.InlineCall(Dst, CE, Pred)) {
+        return;
+      }
+      
+      StmtNodeBuilder &Builder = Eng.getBuilder();
+      assert(&Builder && "StmtNodeBuilder must be defined.");
+      
+      // Dispatch to the plug-in transfer function.
+      unsigned oldSize = Dst.size();
+      SaveOr OldHasGen(Builder.hasGeneratedNode);
+      
+      // Dispatch to transfer function logic to handle the call itself.
+      const Expr *Callee = CE->getCallee()->IgnoreParens();
+      const ProgramState *state = Pred->getState();
+      SVal L = state->getSVal(Callee);
+      Eng.getTF().evalCall(Dst, Eng, Builder, CE, L, 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() == oldSize &&
+          !Builder.hasGeneratedNode)
+        Eng.MakeNode(Dst, CE, Pred, state);
+    }
+  };
+  
+  // Finally, evaluate the function call.  We try each of the checkers
+  // to see if the can evaluate the function call.
+  ExplodedNodeSet dstCallEvaluated;
+  DefaultEval defEval(*this, CE);
+  getCheckerManager().runCheckersForEvalCall(dstCallEvaluated,
+                                             dstPreVisit,
+                                             CE, *this, &defEval);
+  
+  // Finally, perform the post-condition check of the CallExpr and store
+  // the created nodes in 'Dst'.
+  getCheckerManager().runCheckersForPostStmt(dst, dstCallEvaluated, CE,
+                                             *this);
+}
+
+void ExprEngine::VisitReturnStmt(const ReturnStmt *RS, ExplodedNode *Pred,
+                                 ExplodedNodeSet &Dst) {
+  ExplodedNodeSet Src;
+  if (const Expr *RetE = RS->getRetValue()) {
+    // Record the returned expression in the state. It will be used in
+    // processCallExit to bind the return value to the call expr.
+    {
+      static SimpleProgramPointTag tag("ExprEngine: ReturnStmt");
+      const ProgramState *state = Pred->getState();
+      state = state->set<ReturnExpr>(RetE);
+      Pred = Builder->generateNode(RetE, state, Pred, &tag);
+    }
+    // We may get a NULL Pred because we generated a cached node.
+    if (Pred)
+      Visit(RetE, Pred, Src);
+  }
+  else {
+    Src.Add(Pred);
+  }
+  
+  ExplodedNodeSet CheckedSet;
+  getCheckerManager().runCheckersForPreStmt(CheckedSet, Src, RS, *this);
+  
+  for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end();
+       I != E; ++I) {
+    
+    assert(Builder && "StmtNodeBuilder must be defined.");
+    
+    Pred = *I;
+    unsigned size = Dst.size();
+    
+    SaveAndRestore<bool> OldSink(Builder->BuildSinks);
+    SaveOr OldHasGen(Builder->hasGeneratedNode);
+    
+    getTF().evalReturn(Dst, *this, *Builder, RS, Pred);
+    
+    // Handle the case where no nodes where generated.
+    if (!Builder->BuildSinks && Dst.size() == size &&
+        !Builder->hasGeneratedNode)
+      MakeNode(Dst, RS, Pred, Pred->getState());
+  }
+}

Added: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp?rev=138194&view=auto
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp (added)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp Sat Aug 20 01:00:03 2011
@@ -0,0 +1,245 @@
+//=-- ExprEngineObjC.cpp - ExprEngine support for Objective-C ---*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file defines ExprEngine's support for Objective-C expressions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+#include "clang/Analysis/Support/SaveAndRestore.h"
+
+using namespace clang;
+using namespace ento;
+
+void ExprEngine::VisitLvalObjCIvarRefExpr(const ObjCIvarRefExpr *Ex, 
+                                          ExplodedNode *Pred,
+                                          ExplodedNodeSet &Dst) {
+  
+  const ProgramState *state = Pred->getState();
+  SVal baseVal = state->getSVal(Ex->getBase());
+  SVal location = state->getLValue(Ex->getDecl(), baseVal);
+  
+  ExplodedNodeSet dstIvar;
+  MakeNode(dstIvar, Ex, Pred, state->BindExpr(Ex, location));
+  
+  // Perform the post-condition check of the ObjCIvarRefExpr and store
+  // the created nodes in 'Dst'.
+  getCheckerManager().runCheckersForPostStmt(Dst, dstIvar, Ex, *this);
+}
+
+void ExprEngine::VisitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt *S,
+                                             ExplodedNode *Pred,
+                                             ExplodedNodeSet &Dst) {
+  getCheckerManager().runCheckersForPreStmt(Dst, Pred, S, *this);
+}
+
+void ExprEngine::VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S,
+                                            ExplodedNode *Pred,
+                                            ExplodedNodeSet &Dst) {
+  
+  // ObjCForCollectionStmts are processed in two places.  This method
+  // handles the case where an ObjCForCollectionStmt* occurs as one of the
+  // statements within a basic block.  This transfer function does two things:
+  //
+  //  (1) binds the next container value to 'element'.  This creates a new
+  //      node in the ExplodedGraph.
+  //
+  //  (2) binds the value 0/1 to the ObjCForCollectionStmt* itself, indicating
+  //      whether or not the container has any more elements.  This value
+  //      will be tested in ProcessBranch.  We need to explicitly bind
+  //      this value because a container can contain nil elements.
+  //
+  // FIXME: Eventually this logic should actually do dispatches to
+  //   'countByEnumeratingWithState:objects:count:' (NSFastEnumeration).
+  //   This will require simulating a temporary NSFastEnumerationState, either
+  //   through an SVal or through the use of MemRegions.  This value can
+  //   be affixed to the ObjCForCollectionStmt* instead of 0/1; when the loop
+  //   terminates we reclaim the temporary (it goes out of scope) and we
+  //   we can test if the SVal is 0 or if the MemRegion is null (depending
+  //   on what approach we take).
+  //
+  //  For now: simulate (1) by assigning either a symbol or nil if the
+  //    container is empty.  Thus this transfer function will by default
+  //    result in state splitting.
+  
+  const Stmt *elem = S->getElement();
+  const ProgramState *state = Pred->getState();
+  SVal elementV;
+  
+  if (const DeclStmt *DS = dyn_cast<DeclStmt>(elem)) {
+    const VarDecl *elemD = cast<VarDecl>(DS->getSingleDecl());
+    assert(elemD->getInit() == 0);
+    elementV = state->getLValue(elemD, Pred->getLocationContext());
+  }
+  else {
+    elementV = state->getSVal(elem);
+  }
+  
+  ExplodedNodeSet dstLocation;
+  evalLocation(dstLocation, elem, Pred, state, elementV, NULL, false);
+  
+  if (dstLocation.empty())
+    return;
+  
+  for (ExplodedNodeSet::iterator NI = dstLocation.begin(),
+       NE = dstLocation.end(); NI!=NE; ++NI) {
+    Pred = *NI;
+    const ProgramState *state = Pred->getState();
+    
+    // Handle the case where the container still has elements.
+    SVal TrueV = svalBuilder.makeTruthVal(1);
+    const ProgramState *hasElems = state->BindExpr(S, TrueV);
+    
+    // Handle the case where the container has no elements.
+    SVal FalseV = svalBuilder.makeTruthVal(0);
+    const ProgramState *noElems = state->BindExpr(S, FalseV);
+    
+    if (loc::MemRegionVal *MV = dyn_cast<loc::MemRegionVal>(&elementV))
+      if (const TypedValueRegion *R = 
+          dyn_cast<TypedValueRegion>(MV->getRegion())) {
+        // FIXME: The proper thing to do is to really iterate over the
+        //  container.  We will do this with dispatch logic to the store.
+        //  For now, just 'conjure' up a symbolic value.
+        QualType T = R->getValueType();
+        assert(Loc::isLocType(T));
+        unsigned Count = Builder->getCurrentBlockCount();
+        SymbolRef Sym = SymMgr.getConjuredSymbol(elem, T, Count);
+        SVal V = svalBuilder.makeLoc(Sym);
+        hasElems = hasElems->bindLoc(elementV, V);
+        
+        // Bind the location to 'nil' on the false branch.
+        SVal nilV = svalBuilder.makeIntVal(0, T);
+        noElems = noElems->bindLoc(elementV, nilV);
+      }
+    
+    // Create the new nodes.
+    MakeNode(Dst, S, Pred, hasElems);
+    MakeNode(Dst, S, Pred, noElems);
+  }
+}
+
+void ExprEngine::VisitObjCMessage(const ObjCMessage &msg,
+                                  ExplodedNode *Pred,
+                                  ExplodedNodeSet &Dst) {
+  
+  // Handle the previsits checks.
+  ExplodedNodeSet dstPrevisit;
+  getCheckerManager().runCheckersForPreObjCMessage(dstPrevisit, Pred, 
+                                                   msg, *this);
+  
+  // Proceed with evaluate the message expression.
+  ExplodedNodeSet dstEval;
+  
+  for (ExplodedNodeSet::iterator DI = dstPrevisit.begin(),
+       DE = dstPrevisit.end(); DI != DE; ++DI) {
+    
+    ExplodedNode *Pred = *DI;
+    bool RaisesException = false;
+    unsigned oldSize = dstEval.size();
+    SaveAndRestore<bool> OldSink(Builder->BuildSinks);
+    SaveOr OldHasGen(Builder->hasGeneratedNode);
+    
+    if (const Expr *Receiver = msg.getInstanceReceiver()) {
+      const ProgramState *state = Pred->getState();
+      SVal recVal = state->getSVal(Receiver);
+      if (!recVal.isUndef()) {
+        // Bifurcate the state into nil and non-nil ones.
+        DefinedOrUnknownSVal receiverVal = cast<DefinedOrUnknownSVal>(recVal);
+        
+        const ProgramState *notNilState, *nilState;
+        llvm::tie(notNilState, nilState) = state->assume(receiverVal);
+        
+        // There are three cases: can be nil or non-nil, must be nil, must be
+        // non-nil. We ignore must be nil, and merge the rest two into non-nil.
+        if (nilState && !notNilState) {
+          dstEval.insert(Pred);
+          continue;
+        }
+        
+        // Check if the "raise" message was sent.
+        assert(notNilState);
+        if (msg.getSelector() == RaiseSel)
+          RaisesException = true;
+        
+        // Check if we raise an exception.  For now treat these as sinks.
+        // Eventually we will want to handle exceptions properly.
+        if (RaisesException)
+          Builder->BuildSinks = true;
+        
+        // Dispatch to plug-in transfer function.
+        evalObjCMessage(dstEval, msg, Pred, notNilState);
+      }
+    }
+    else if (const ObjCInterfaceDecl *Iface = msg.getReceiverInterface()) {
+      IdentifierInfo* ClsName = Iface->getIdentifier();
+      Selector S = msg.getSelector();
+      
+      // Check for special instance methods.
+      if (!NSExceptionII) {
+        ASTContext &Ctx = getContext();
+        NSExceptionII = &Ctx.Idents.get("NSException");
+      }
+      
+      if (ClsName == NSExceptionII) {
+        enum { NUM_RAISE_SELECTORS = 2 };
+        
+        // Lazily create a cache of the selectors.
+        if (!NSExceptionInstanceRaiseSelectors) {
+          ASTContext &Ctx = getContext();
+          NSExceptionInstanceRaiseSelectors =
+          new Selector[NUM_RAISE_SELECTORS];
+          SmallVector<IdentifierInfo*, NUM_RAISE_SELECTORS> II;
+          unsigned idx = 0;
+          
+          // raise:format:
+          II.push_back(&Ctx.Idents.get("raise"));
+          II.push_back(&Ctx.Idents.get("format"));
+          NSExceptionInstanceRaiseSelectors[idx++] =
+          Ctx.Selectors.getSelector(II.size(), &II[0]);
+          
+          // raise:format::arguments:
+          II.push_back(&Ctx.Idents.get("arguments"));
+          NSExceptionInstanceRaiseSelectors[idx++] =
+          Ctx.Selectors.getSelector(II.size(), &II[0]);
+        }
+        
+        for (unsigned i = 0; i < NUM_RAISE_SELECTORS; ++i)
+          if (S == NSExceptionInstanceRaiseSelectors[i]) {
+            RaisesException = true;
+            break;
+          }
+      }
+      
+      // Check if we raise an exception.  For now treat these as sinks.
+      // Eventually we will want to handle exceptions properly.
+      if (RaisesException)
+        Builder->BuildSinks = true;
+      
+      // Dispatch to plug-in transfer function.
+      evalObjCMessage(dstEval, msg, Pred, Pred->getState());
+    }
+    
+    // Handle the case where no nodes where generated.  Auto-generate that
+    // contains the updated state if we aren't generating sinks.
+    if (!Builder->BuildSinks && dstEval.size() == oldSize &&
+        !Builder->hasGeneratedNode)
+      MakeNode(dstEval, msg.getOriginExpr(), Pred, Pred->getState());
+  }
+  
+  // Finally, perform the post-condition check of the ObjCMessageExpr and store
+  // the created nodes in 'Dst'.
+  getCheckerManager().runCheckersForPostObjCMessage(Dst, dstEval, msg, *this);
+}
+
+void ExprEngine::VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *Ex,
+                                          ExplodedNode *Pred,
+                                          ExplodedNodeSet &Dst) {
+  MakeNode(Dst, Ex, Pred, Pred->getState()->BindExpr(Ex, loc::ObjCPropRef(Ex)));
+}





More information about the cfe-commits mailing list