[analyzer] Track null/uninitialized C++ objects used in method calls.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@161278 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp b/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
index 439b920..70b6241 100644
--- a/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
@@ -51,7 +51,7 @@
                                  bool IsFirstArgument, bool checkUninitFields,
                                  const CallEvent &Call, OwningPtr<BugType> &BT);
 
-  static void EmitBadCall(BugType *BT, CheckerContext &C, const CallExpr *CE);
+  static void emitBadCall(BugType *BT, CheckerContext &C, const Expr *BadE);
   void emitNilReceiverBug(CheckerContext &C, const ObjCMethodCall &msg,
                           ExplodedNode *N) const;
 
@@ -66,15 +66,17 @@
 };
 } // end anonymous namespace
 
-void CallAndMessageChecker::EmitBadCall(BugType *BT, CheckerContext &C,
-                                        const CallExpr *CE) {
+void CallAndMessageChecker::emitBadCall(BugType *BT, CheckerContext &C,
+                                        const Expr *BadE) {
   ExplodedNode *N = C.generateSink();
   if (!N)
     return;
 
   BugReport *R = new BugReport(*BT, BT->getName(), N);
-  R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N,
-                               bugreporter::GetCalleeExpr(N), R));
+  if (BadE) {
+    R->addRange(BadE->getSourceRange());
+    R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, BadE, R));
+  }
   C.EmitReport(R);
 }
 
@@ -227,7 +229,7 @@
     if (!BT_call_undef)
       BT_call_undef.reset(new BuiltinBug("Called function pointer is an "
                                          "uninitalized pointer value"));
-    EmitBadCall(BT_call_undef.get(), C, CE);
+    emitBadCall(BT_call_undef.get(), C, Callee);
     return;
   }
 
@@ -235,7 +237,7 @@
     if (!BT_call_null)
       BT_call_null.reset(
         new BuiltinBug("Called function pointer is null (null dereference)"));
-    EmitBadCall(BT_call_null.get(), C, CE);
+    emitBadCall(BT_call_null.get(), C, Callee);
   }
 }
 
@@ -243,22 +245,20 @@
                                          CheckerContext &C) const {
   // If this is a call to a C++ method, check if the callee is null or
   // undefined.
-  // FIXME: Generalize this to CXXInstanceCall once it supports
-  // getCXXThisVal().
-  if (const CXXMemberCall *CC = dyn_cast<CXXMemberCall>(&Call)) {
+  if (const CXXInstanceCall *CC = dyn_cast<CXXInstanceCall>(&Call)) {
     SVal V = CC->getCXXThisVal();
     if (V.isUndef()) {
       if (!BT_cxx_call_undef)
         BT_cxx_call_undef.reset(new BuiltinBug("Called C++ object pointer is "
                                                "uninitialized"));
-      EmitBadCall(BT_cxx_call_undef.get(), C, CC->getOriginExpr());
+      emitBadCall(BT_cxx_call_undef.get(), C, CC->getCXXThisExpr());
       return;
     }
     if (V.isZeroConstant()) {
       if (!BT_cxx_call_null)
         BT_cxx_call_null.reset(new BuiltinBug("Called C++ object pointer "
                                               "is null"));
-      EmitBadCall(BT_cxx_call_null.get(), C, CC->getOriginExpr());
+      emitBadCall(BT_cxx_call_null.get(), C, CC->getCXXThisExpr());
       return;
     }
   }