[analyzer] Convert CallAndMessageChecker and ObjCSelfInitChecker to CallEvent.

Both of these got uglier rather than cleaner because we don't have preCall and
postCall yet; properly wrapping a CallExpr in a CallEvent requires doing a bit
of deconstruction on the callee. Even when we have preCall and postCall we may
want to expose the current CallEvent to pre/postStmt<CallExpr>.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@159556 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp b/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
index 6d9ce0a..11a9ab3 100644
--- a/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
@@ -15,6 +15,7 @@
 #include "ClangSACheckers.h"
 #include "clang/StaticAnalyzer/Core/Checker.h"
 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/Calls.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
@@ -41,7 +42,7 @@
   void checkPreObjCMessage(ObjCMessage msg, CheckerContext &C) const;
 
 private:
-  static void PreVisitProcessArgs(CheckerContext &C,CallOrObjCMessage callOrMsg,
+  static void PreVisitProcessArgs(CheckerContext &C, const CallEvent &Call,
                              const char *BT_desc, OwningPtr<BugType> &BT);
   static bool PreVisitProcessArg(CheckerContext &C, SVal V,SourceRange argRange,
                                  const Expr *argEx,
@@ -77,23 +78,22 @@
 }
 
 void CallAndMessageChecker::PreVisitProcessArgs(CheckerContext &C,
-                                                CallOrObjCMessage callOrMsg,
+                                                const CallEvent &Call,
                                                 const char *BT_desc,
                                                 OwningPtr<BugType> &BT) {
   // Don't check for uninitialized field values in arguments if the
   // caller has a body that is available and we have the chance to inline it.
   // This is a hack, but is a reasonable compromise betweens sometimes warning
   // and sometimes not depending on if we decide to inline a function.
-  const Decl *D = callOrMsg.getDecl();
+  const Decl *D = Call.getDecl();
   const bool checkUninitFields =
     !(C.getAnalysisManager().shouldInlineCall() &&
       (D && D->getBody()));
   
-  for (unsigned i = 0, e = callOrMsg.getNumArgs(); i != e; ++i)
-    if (PreVisitProcessArg(C, callOrMsg.getArgSVal(i),
-                           callOrMsg.getArgSourceRange(i), callOrMsg.getArg(i),
-                           checkUninitFields,
-                           BT_desc, BT))
+  for (unsigned i = 0, e = Call.getNumArgs(); i != e; ++i)
+    if (PreVisitProcessArg(C, Call.getArgSVal(i),
+                           Call.getArgSourceRange(i), Call.getArgExpr(i),
+                           checkUninitFields, BT_desc, BT))
       return;
 }
 
@@ -210,8 +210,9 @@
                                          CheckerContext &C) const{
 
   const Expr *Callee = CE->getCallee()->IgnoreParens();
+  ProgramStateRef State = C.getState();
   const LocationContext *LCtx = C.getLocationContext();
-  SVal L = C.getState()->getSVal(Callee, LCtx);
+  SVal L = State->getSVal(Callee, LCtx);
 
   if (L.isUndef()) {
     if (!BT_call_undef)
@@ -221,16 +222,30 @@
     return;
   }
 
-  if (isa<loc::ConcreteInt>(L)) {
+  if (L.isZeroConstant()) {
     if (!BT_call_null)
       BT_call_null.reset(
         new BuiltinBug("Called function pointer is null (null dereference)"));
     EmitBadCall(BT_call_null.get(), C, CE);
   }
 
-  PreVisitProcessArgs(C, CallOrObjCMessage(CE, C.getState(), LCtx),
-                      "Function call argument is an uninitialized value",
-                      BT_call_arg);
+  // FIXME: This tree of switching can go away if/when we add a check::postCall.
+  if (dyn_cast_or_null<BlockDataRegion>(L.getAsRegion())) {
+    BlockCall Call(CE, State, LCtx);
+    PreVisitProcessArgs(C, Call,
+                        "Block call argument is an uninitialized value",
+                        BT_call_arg);
+  } else if (const CXXMemberCallExpr *me = dyn_cast<CXXMemberCallExpr>(CE)) {
+    CXXMemberCall Call(me, State, LCtx);
+    PreVisitProcessArgs(C, Call,
+                        "Function call argument is an uninitialized value",
+                        BT_call_arg);
+  } else {
+    FunctionCall Call(CE, State, LCtx);
+    PreVisitProcessArgs(C, Call,
+                        "Function call argument is an uninitialized value",
+                        BT_call_arg);
+  }
 }
 
 void CallAndMessageChecker::checkPreObjCMessage(ObjCMessage msg,
@@ -285,7 +300,7 @@
                      "Argument for property setter is an uninitialized value"
                    : "Argument in message expression is an uninitialized value";
   // Check for any arguments that are uninitialized/undefined.
-  PreVisitProcessArgs(C, CallOrObjCMessage(msg, state, LCtx),
+  PreVisitProcessArgs(C, ObjCMessageInvocation(msg, state, LCtx),
                       bugDesc, BT_msg_arg);
 }
 
diff --git a/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp b/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
index 89340cc..bb6ab6f 100644
--- a/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
@@ -39,6 +39,7 @@
 #include "ClangSACheckers.h"
 #include "clang/StaticAnalyzer/Core/Checker.h"
 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/Calls.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h"
@@ -73,8 +74,8 @@
                      CheckerContext &C) const;
   void checkBind(SVal loc, SVal val, const Stmt *S, CheckerContext &C) const;
 
-  void checkPreStmt(const CallOrObjCMessage &CE, CheckerContext &C) const;
-  void checkPostStmt(const CallOrObjCMessage &CE, CheckerContext &C) const;
+  void checkPreStmt(const CallEvent &CE, CheckerContext &C) const;
+  void checkPostStmt(const CallEvent &CE, CheckerContext &C) const;
 
 };
 } // end anonymous namespace
@@ -208,7 +209,7 @@
     return;
   }
 
-  CallOrObjCMessage MsgWrapper(msg, C.getState(), C.getLocationContext());
+  ObjCMessageInvocation MsgWrapper(msg, C.getState(), C.getLocationContext());
   checkPostStmt(MsgWrapper, C);
 
   // We don't check for an invalid 'self' in an obj-c message expression to cut
@@ -259,23 +260,51 @@
 
 void ObjCSelfInitChecker::checkPreStmt(const CallExpr *CE,
                                        CheckerContext &C) const {
-  CallOrObjCMessage CEWrapper(CE, C.getState(), C.getLocationContext());
-  checkPreStmt(CEWrapper, C);
+  // FIXME: This tree of switching can go away if/when we add a check::postCall.
+  const Expr *Callee = CE->getCallee()->IgnoreParens();
+  ProgramStateRef State = C.getState();
+  const LocationContext *LCtx = C.getLocationContext();
+  SVal L = State->getSVal(Callee, LCtx);
+
+  if (dyn_cast_or_null<BlockDataRegion>(L.getAsRegion())) {
+    BlockCall Call(CE, State, LCtx);
+    checkPreStmt(Call, C);
+  } else if (const CXXMemberCallExpr *me = dyn_cast<CXXMemberCallExpr>(CE)) {
+    CXXMemberCall Call(me, State, LCtx);
+    checkPreStmt(Call, C);
+  } else {
+    FunctionCall Call(CE, State, LCtx);
+    checkPreStmt(Call, C);
+  }
 }
 
 void ObjCSelfInitChecker::checkPostStmt(const CallExpr *CE,
                                         CheckerContext &C) const {
-  CallOrObjCMessage CEWrapper(CE, C.getState(), C.getLocationContext());
-  checkPostStmt(CEWrapper, C);
+  // FIXME: This tree of switching can go away if/when we add a check::postCall.
+  const Expr *Callee = CE->getCallee()->IgnoreParens();
+  ProgramStateRef State = C.getState();
+  const LocationContext *LCtx = C.getLocationContext();
+  SVal L = State->getSVal(Callee, LCtx);
+
+  if (dyn_cast_or_null<BlockDataRegion>(L.getAsRegion())) {
+    BlockCall Call(CE, State, LCtx);
+    checkPostStmt(Call, C);
+  } else if (const CXXMemberCallExpr *me = dyn_cast<CXXMemberCallExpr>(CE)) {
+    CXXMemberCall Call(me, State, LCtx);
+    checkPostStmt(Call, C);
+  } else {
+    FunctionCall Call(CE, State, LCtx);
+    checkPostStmt(Call, C);
+  }
 }
 
 void ObjCSelfInitChecker::checkPreObjCMessage(ObjCMessage Msg,
                                               CheckerContext &C) const {
-  CallOrObjCMessage MsgWrapper(Msg, C.getState(), C.getLocationContext());
+  ObjCMessageInvocation MsgWrapper(Msg, C.getState(), C.getLocationContext());
   checkPreStmt(MsgWrapper, C);
 }
 
-void ObjCSelfInitChecker::checkPreStmt(const CallOrObjCMessage &CE,
+void ObjCSelfInitChecker::checkPreStmt(const CallEvent &CE,
                                        CheckerContext &C) const {
   ProgramStateRef state = C.getState();
   unsigned NumArgs = CE.getNumArgs();
@@ -298,7 +327,7 @@
   }
 }
 
-void ObjCSelfInitChecker::checkPostStmt(const CallOrObjCMessage &CE,
+void ObjCSelfInitChecker::checkPostStmt(const CallEvent &CE,
                                         CheckerContext &C) const {
   ProgramStateRef state = C.getState();
   unsigned NumArgs = CE.getNumArgs();