Hard bifurcate the state into nil receiver and non-nil receiver, so that
we don't need to use the DoneEvaluation hack when check for 
ObjCMessageExpr.

PreVisitObjCMessageExpr() only checks for undefined receiver or arguments.

Add checker interface EvalNilReceiver(). This is a 'once-and-done' interface.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@90296 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Analysis/CallAndMessageChecker.cpp b/lib/Analysis/CallAndMessageChecker.cpp
index d8dd16c..c287354 100644
--- a/lib/Analysis/CallAndMessageChecker.cpp
+++ b/lib/Analysis/CallAndMessageChecker.cpp
@@ -41,6 +41,7 @@
 
   void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
   void PreVisitObjCMessageExpr(CheckerContext &C, const ObjCMessageExpr *ME);
+  bool EvalNilReceiver(CheckerContext &C, const ObjCMessageExpr *ME);
 
 private:
   void EmitBadCall(BugType *BT, CheckerContext &C, const CallExpr *CE);
@@ -148,28 +149,12 @@
       }
     }
   }
+}
 
-  // Check if the receiver was nil and then returns a value that may
-  // be garbage.
-  if (const Expr *Receiver = ME->getReceiver()) {
-    DefinedOrUnknownSVal receiverVal =
-      cast<DefinedOrUnknownSVal>(state->getSVal(Receiver));
-    
-    const GRState *notNullState, *nullState;
-    llvm::tie(notNullState, nullState) = state->Assume(receiverVal);
-    
-    if (nullState && !notNullState) {
-      HandleNilReceiver(C, nullState, ME);
-      C.setDoneEvaluating(); // FIXME: eventually remove.
-      return;
-    }
-    
-    assert(notNullState);
-    state = notNullState;
-  }
-  
-  // Add a state transition if the state has changed.
-  C.addTransition(state);
+bool CallAndMessageChecker::EvalNilReceiver(CheckerContext &C,
+                                            const ObjCMessageExpr *ME) {
+  HandleNilReceiver(C, C.getState(), ME);
+  return true; // Nil receiver is not handled elsewhere.
 }
 
 void CallAndMessageChecker::EmitNilReceiverBug(CheckerContext &C,