Pull BadCallChecker int UndefinedArgChecker, and have UndefinedArgChecker also handled undefined receivers in message expressions.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89524 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Analysis/PathSensitive/GRExprEngine.h b/include/clang/Analysis/PathSensitive/GRExprEngine.h
index 75f04b6..cca548e 100644
--- a/include/clang/Analysis/PathSensitive/GRExprEngine.h
+++ b/include/clang/Analysis/PathSensitive/GRExprEngine.h
@@ -126,10 +126,6 @@
   ///  by the result is not.  Excludes divide-by-zero errors.
   ErrorNodes UndefResults;
 
-  /// UndefReceiver - Nodes in the ExplodedGraph resulting from message
-  ///  ObjC message expressions where the receiver is undefined (uninitialized).
-  ErrorNodes UndefReceivers;
-
 public:
   GRExprEngine(AnalysisManager &mgr);
 
@@ -223,16 +219,6 @@
   undef_result_iterator undef_results_begin() { return UndefResults.begin(); }
   undef_result_iterator undef_results_end() { return UndefResults.end(); }
 
-  typedef ErrorNodes::iterator undef_receivers_iterator;
-
-  undef_receivers_iterator undef_receivers_begin() {
-    return UndefReceivers.begin();
-  }
-
-  undef_receivers_iterator undef_receivers_end() {
-    return UndefReceivers.end();
-  }
-
   void AddCheck(GRSimpleAPICheck* A, Stmt::StmtClass C);
   void AddCheck(GRSimpleAPICheck* A);
 
diff --git a/lib/Analysis/BadCallChecker.cpp b/lib/Analysis/BadCallChecker.cpp
deleted file mode 100644
index 7a7ea18..0000000
--- a/lib/Analysis/BadCallChecker.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-//===--- BadCallChecker.h - Bad call checker --------------------*- C++ -*--==//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This defines BadCallChecker, a builtin check in GRExprEngine that performs
-// checks for bad callee at call sites.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
-#include "clang/Analysis/PathSensitive/BugReporter.h"
-#include "GRExprEngineInternalChecks.h"
-
-using namespace clang;
-
-namespace {
-class VISIBILITY_HIDDEN BadCallChecker : public CheckerVisitor<BadCallChecker> {
-  BuiltinBug *BT;
-public:
-  BadCallChecker() : BT(0) {}
-  static void *getTag() {
-    static int x = 0;
-    return &x;
-  }
-  void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
-};
-} // end anonymous namespace
-
-void clang::RegisterBadCallChecker(GRExprEngine &Eng) {
-  Eng.registerCheck(new BadCallChecker());
-}
-
-void BadCallChecker::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
-  const Expr *Callee = CE->getCallee()->IgnoreParens();
-  SVal L = C.getState()->getSVal(Callee);
-
-  if (L.isUndef() || isa<loc::ConcreteInt>(L)) {
-    if (ExplodedNode *N = C.GenerateNode(CE, true)) {
-      if (!BT)
-        BT = new BuiltinBug("Invalid function call",
-                "Called function pointer is a null or undefined pointer value");
-
-      EnhancedBugReport *R =
-        new EnhancedBugReport(*BT, BT->getDescription(), N);
-        
-      R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
-                           bugreporter::GetCalleeExpr(N));
-
-      C.EmitReport(R);
-    }
-  }
-}
diff --git a/lib/Analysis/CMakeLists.txt b/lib/Analysis/CMakeLists.txt
index 8e8c1e7..37852a0 100644
--- a/lib/Analysis/CMakeLists.txt
+++ b/lib/Analysis/CMakeLists.txt
@@ -4,7 +4,6 @@
   AnalysisContext.cpp
   ArrayBoundChecker.cpp
   AttrNonNullChecker.cpp
-  BadCallChecker.cpp
   BasicConstraintManager.cpp
   BasicObjCFoundationChecks.cpp
   BasicStore.cpp
diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp
index 047e27d..f5fe8d0 100644
--- a/lib/Analysis/GRExprEngine.cpp
+++ b/lib/Analysis/GRExprEngine.cpp
@@ -1850,177 +1850,164 @@
                                                       ExplodedNode* Pred,
                                                       ExplodedNodeSet& Dst) {
 
-  // FIXME: More logic for the processing the method call.
-
-  const GRState* state = GetState(Pred);
-  bool RaisesException = false;
-
-
-  if (Expr* Receiver = ME->getReceiver()) {
-
-    SVal L_untested = state->getSVal(Receiver);
-
-    // Check for undefined control-flow.
-    if (L_untested.isUndef()) {
-      ExplodedNode* N = Builder->generateNode(ME, state, Pred);
-
-      if (N) {
-        N->markAsSink();
-        UndefReceivers.insert(N);
-      }
-
-      return;
-    }
-
-    // "Assume" that the receiver is not NULL.
-    DefinedOrUnknownSVal L = cast<DefinedOrUnknownSVal>(L_untested);
-    const GRState *StNotNull = state->Assume(L, true);
-
-    // "Assume" that the receiver is NULL.
-    const GRState *StNull = state->Assume(L, false);
-
-    if (StNull) {
-      QualType RetTy = ME->getType();
-
-      // Check if the receiver was nil and the return value a struct.
-      if (RetTy->isRecordType()) {
-        if (Pred->getParentMap().isConsumedExpr(ME)) {
-          // The [0 ...] expressions will return garbage.  Flag either an
-          // explicit or implicit error.  Because of the structure of this
-          // function we currently do not bifurfacte the state graph at
-          // this point.
-          // FIXME: We should bifurcate and fill the returned struct with
-          //  garbage.
-          if (ExplodedNode* N = Builder->generateNode(ME, StNull, Pred)) {
-            N->markAsSink();
-            if (StNotNull)
-              NilReceiverStructRetImplicit.insert(N);
-            else
-              NilReceiverStructRetExplicit.insert(N);
-          }
-        }
-      }
-      else {
-        ASTContext& Ctx = getContext();
-        if (RetTy != Ctx.VoidTy) {
-          if (Pred->getParentMap().isConsumedExpr(ME)) {
-            // sizeof(void *)
-            const uint64_t voidPtrSize = Ctx.getTypeSize(Ctx.VoidPtrTy);
-            // sizeof(return type)
-            const uint64_t returnTypeSize = Ctx.getTypeSize(ME->getType());
-
-            if (voidPtrSize < returnTypeSize) {
-              if (ExplodedNode* N = Builder->generateNode(ME, StNull, Pred)) {
-                N->markAsSink();
-                if (StNotNull)
-                  NilReceiverLargerThanVoidPtrRetImplicit.insert(N);
-                else
-                  NilReceiverLargerThanVoidPtrRetExplicit.insert(N);
-              }
-            }
-            else if (!StNotNull) {
-              // Handle the safe cases where the return value is 0 if the
-              // receiver is nil.
-              //
-              // FIXME: For now take the conservative approach that we only
-              // return null values if we *know* that the receiver is nil.
-              // This is because we can have surprises like:
-              //
-              //   ... = [[NSScreens screens] objectAtIndex:0];
-              //
-              // What can happen is that [... screens] could return nil, but
-              // it most likely isn't nil.  We should assume the semantics
-              // of this case unless we have *a lot* more knowledge.
-              //
-              SVal V = ValMgr.makeZeroVal(ME->getType());
-              MakeNode(Dst, ME, Pred, StNull->BindExpr(ME, V));
-              return;
-            }
-          }
-        }
-      }
-      // We have handled the cases where the receiver is nil.  The remainder
-      // of this method should assume that the receiver is not nil.
-      if (!StNotNull)
-        return;
-
-      state = StNotNull;
-    }
-
-    // Check if the "raise" message was sent.
-    if (ME->getSelector() == RaiseSel)
-      RaisesException = true;
-  }
-  else {
-
-    IdentifierInfo* ClsName = ME->getClassName();
-    Selector S = ME->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];
-
-        llvm::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;
-        }
-    }
-  }
-
   // Handle previsits checks.
   ExplodedNodeSet Src, DstTmp;
   Src.Add(Pred);  
   CheckerVisit(ME, DstTmp, Src, true);
   
-  // Check if we raise an exception.  For now treat these as sinks.  Eventually
-  // we will want to handle exceptions properly.
-  SaveAndRestore<bool> OldSink(Builder->BuildSinks);
-  if (RaisesException)
-    Builder->BuildSinks = true;
-
-  // Dispatch to plug-in transfer function.
   unsigned size = Dst.size();
-  SaveOr OldHasGen(Builder->HasGeneratedNode);
-  
+
   for (ExplodedNodeSet::iterator DI = DstTmp.begin(), DE = DstTmp.end();
-       DI!=DE; ++DI)
-    EvalObjCMessageExpr(Dst, ME, *DI);
+       DI!=DE; ++DI) {    
+    Pred = *DI;
+    // FIXME: More logic for the processing the method call.
+    const GRState* state = GetState(Pred);
+    bool RaisesException = false;
+
+    if (Expr* Receiver = ME->getReceiver()) {
+      SVal L_untested = state->getSVal(Receiver);
+
+      // "Assume" that the receiver is not NULL.
+      DefinedOrUnknownSVal L = cast<DefinedOrUnknownSVal>(L_untested);
+      const GRState *StNotNull = state->Assume(L, true);
+
+      // "Assume" that the receiver is NULL.
+      const GRState *StNull = state->Assume(L, false);
+
+      if (StNull) {
+        QualType RetTy = ME->getType();
+
+        // Check if the receiver was nil and the return value a struct.
+        if (RetTy->isRecordType()) {
+          if (Pred->getParentMap().isConsumedExpr(ME)) {
+            // The [0 ...] expressions will return garbage.  Flag either an
+            // explicit or implicit error.  Because of the structure of this
+            // function we currently do not bifurfacte the state graph at
+            // this point.
+            // FIXME: We should bifurcate and fill the returned struct with
+            //  garbage.
+            if (ExplodedNode* N = Builder->generateNode(ME, StNull, Pred)) {
+              N->markAsSink();
+              if (StNotNull)
+                NilReceiverStructRetImplicit.insert(N);
+              else
+                NilReceiverStructRetExplicit.insert(N);
+            }
+          }
+        }
+        else {
+          ASTContext& Ctx = getContext();
+          if (RetTy != Ctx.VoidTy) {
+            if (Pred->getParentMap().isConsumedExpr(ME)) {
+              // sizeof(void *)
+              const uint64_t voidPtrSize = Ctx.getTypeSize(Ctx.VoidPtrTy);
+              // sizeof(return type)
+              const uint64_t returnTypeSize = Ctx.getTypeSize(ME->getType());
+
+              if (voidPtrSize < returnTypeSize) {
+                if (ExplodedNode* N = Builder->generateNode(ME, StNull, Pred)) {
+                  N->markAsSink();
+                  if (StNotNull)
+                    NilReceiverLargerThanVoidPtrRetImplicit.insert(N);
+                  else
+                    NilReceiverLargerThanVoidPtrRetExplicit.insert(N);
+                }
+              }
+              else if (!StNotNull) {
+                // Handle the safe cases where the return value is 0 if the
+                // receiver is nil.
+                //
+                // FIXME: For now take the conservative approach that we only
+                // return null values if we *know* that the receiver is nil.
+                // This is because we can have surprises like:
+                //
+                //   ... = [[NSScreens screens] objectAtIndex:0];
+                //
+                // What can happen is that [... screens] could return nil, but
+                // it most likely isn't nil.  We should assume the semantics
+                // of this case unless we have *a lot* more knowledge.
+                //
+                SVal V = ValMgr.makeZeroVal(ME->getType());
+                MakeNode(Dst, ME, Pred, StNull->BindExpr(ME, V));
+                return;
+              }
+            }
+          }
+        }
+        // We have handled the cases where the receiver is nil.  The remainder
+        // of this method should assume that the receiver is not nil.
+        if (!StNotNull)
+          return;
+
+        state = StNotNull;
+      }
+
+      // Check if the "raise" message was sent.
+      if (ME->getSelector() == RaiseSel)
+        RaisesException = true;
+    }
+    else {
+
+      IdentifierInfo* ClsName = ME->getClassName();
+      Selector S = ME->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];
+
+          llvm::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.
+    SaveAndRestore<bool> OldSink(Builder->BuildSinks);
+    if (RaisesException)
+      Builder->BuildSinks = true;
+
+    // Dispatch to plug-in transfer function.
+    SaveOr OldHasGen(Builder->HasGeneratedNode);  
+    EvalObjCMessageExpr(Dst, ME, Pred);
+  }
 
   // Handle the case where no nodes where generated.  Auto-generate that
   // contains the updated state if we aren't generating sinks.
   if (!Builder->BuildSinks && Dst.size() == size && !Builder->HasGeneratedNode)
-    MakeNode(Dst, ME, Pred, state);
+    MakeNode(Dst, ME, Pred, GetState(Pred));
 }
 
 //===----------------------------------------------------------------------===//
diff --git a/lib/Analysis/GRExprEngineInternalChecks.cpp b/lib/Analysis/GRExprEngineInternalChecks.cpp
index 50e855f..8fcb3b7 100644
--- a/lib/Analysis/GRExprEngineInternalChecks.cpp
+++ b/lib/Analysis/GRExprEngineInternalChecks.cpp
@@ -219,34 +219,6 @@
   const Stmt *getArg() const { return Arg; }
 };
 
-class VISIBILITY_HIDDEN BadReceiver : public BuiltinBug {
-public:
-  BadReceiver(GRExprEngine* eng)
-  : BuiltinBug(eng,"Uninitialized receiver",
-               "Receiver in message expression is an uninitialized value") {}
-
-  void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
-    for (GRExprEngine::ErrorNodes::iterator I=Eng.undef_receivers_begin(),
-         End = Eng.undef_receivers_end(); I!=End; ++I) {
-
-      // Generate a report for this bug.
-      BuiltinBugReport *report = new BuiltinBugReport(*this, desc.c_str(), *I);
-      ExplodedNode* N = *I;
-      const Stmt *S = cast<PostStmt>(N->getLocation()).getStmt();
-      const Expr* E = cast<ObjCMessageExpr>(S)->getReceiver();
-      assert (E && "Receiver cannot be NULL");
-      report->addRange(E->getSourceRange());
-      BR.EmitReport(report);
-    }
-  }
-
-  void registerInitialVisitors(BugReporterContext& BRC,
-                               const ExplodedNode* N,
-                               BuiltinBugReport *R) {
-    registerTrackNullOrUndefValue(BRC, GetReceiverExpr(N), N);
-  }
-};
-
 class VISIBILITY_HIDDEN UndefBranch : public BuiltinBug {
   struct VISIBILITY_HIDDEN FindUndefExpr {
     GRStateManager& VM;
@@ -337,7 +309,6 @@
   // to 'FlushReports' from BugReporter.
   BR.Register(new UndefBranch(this));
   BR.Register(new UndefResult(this));
-  BR.Register(new BadReceiver(this));
   BR.Register(new NilReceiverStructRet(this));
   BR.Register(new NilReceiverLargerThanVoidPtrRet(this));
 
@@ -350,7 +321,6 @@
   
   RegisterAttrNonNullChecker(*this);
   RegisterUndefinedArgChecker(*this);
-  RegisterBadCallChecker(*this);
   RegisterDereferenceChecker(*this);
   RegisterVLASizeChecker(*this);
   RegisterDivZeroChecker(*this);
diff --git a/lib/Analysis/GRExprEngineInternalChecks.h b/lib/Analysis/GRExprEngineInternalChecks.h
index a9077bf..5db0013 100644
--- a/lib/Analysis/GRExprEngineInternalChecks.h
+++ b/lib/Analysis/GRExprEngineInternalChecks.h
@@ -20,7 +20,6 @@
 class GRExprEngine;
 
 void RegisterAttrNonNullChecker(GRExprEngine &Eng);
-void RegisterBadCallChecker(GRExprEngine &Eng);
 void RegisterDereferenceChecker(GRExprEngine &Eng);
 void RegisterDivZeroChecker(GRExprEngine &Eng);
 void RegisterReturnPointerRangeChecker(GRExprEngine &Eng);
diff --git a/lib/Analysis/UndefinedArgChecker.cpp b/lib/Analysis/UndefinedArgChecker.cpp
index a0c0d48..ea7d971 100644
--- a/lib/Analysis/UndefinedArgChecker.cpp
+++ b/lib/Analysis/UndefinedArgChecker.cpp
@@ -21,16 +21,23 @@
 namespace {
 class VISIBILITY_HIDDEN UndefinedArgChecker
   : public CheckerVisitor<UndefinedArgChecker> {
-  BugType *BT_call;
-  BugType *BT_msg;
+  BugType *BT_call_null;
+  BugType *BT_call_undef;  
+  BugType *BT_call_arg;
+  BugType *BT_msg_undef;
+  BugType *BT_msg_arg;
 public:
-  UndefinedArgChecker() : BT_call(0), BT_msg(0) {}
+  UndefinedArgChecker() :
+    BT_call_null(0), BT_call_undef(0), BT_call_arg(0),
+    BT_msg_undef(0), BT_msg_arg(0) {}
   static void *getTag() {
     static int x = 0;
     return &x;
   }
   void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
   void PreVisitObjCMessageExpr(CheckerContext &C, const ObjCMessageExpr *ME);
+private:
+  void EmitBadCall(BugType *BT, CheckerContext &C, const CallExpr *CE);
 };
 } // end anonymous namespace
 
@@ -38,18 +45,49 @@
   Eng.registerCheck(new UndefinedArgChecker());
 }
 
+void UndefinedArgChecker::EmitBadCall(BugType *BT, CheckerContext &C,
+                                      const CallExpr *CE) {
+  ExplodedNode *N = C.GenerateNode(CE, true);
+  if (!N)
+    return;
+    
+  EnhancedBugReport *R = new EnhancedBugReport(*BT, BT->getName(), N);
+  R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
+                       bugreporter::GetCalleeExpr(N));
+  C.EmitReport(R);
+}
+
 void UndefinedArgChecker::PreVisitCallExpr(CheckerContext &C, 
                                            const CallExpr *CE){
+  
+  const Expr *Callee = CE->getCallee()->IgnoreParens();
+  SVal L = C.getState()->getSVal(Callee);
+  
+  if (L.isUndef()) {
+    if (!BT_call_undef)
+      BT_call_undef =
+        new BuiltinBug("Called function pointer is an undefined pointer value");
+    EmitBadCall(BT_call_undef, C, CE);
+    return;
+  }
+  
+  if (isa<loc::ConcreteInt>(L)) {
+    if (!BT_call_null)
+      BT_call_null =
+        new BuiltinBug("Called function pointer is null (null dereference)");
+    EmitBadCall(BT_call_null, C, CE);
+  }  
+  
   for (CallExpr::const_arg_iterator I = CE->arg_begin(), E = CE->arg_end();
        I != E; ++I) {
     if (C.getState()->getSVal(*I).isUndef()) {
       if (ExplodedNode *N = C.GenerateNode(CE, true)) {
-        if (!BT_call)
-          BT_call = new BuiltinBug("Pass-by-value argument in function call is "
-                                   "undefined");
+        if (!BT_call_arg)
+          BT_call_arg = new BuiltinBug("Pass-by-value argument in function call"
+                                       " is undefined");
         // Generate a report for this bug.
-        EnhancedBugReport *R = new EnhancedBugReport(*BT_call,
-                                                     BT_call->getName(), N);
+        EnhancedBugReport *R = new EnhancedBugReport(*BT_call_arg,
+                                                     BT_call_arg->getName(), N);
         R->addRange((*I)->getSourceRange());
         R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, *I);
         C.EmitReport(R);
@@ -62,18 +100,36 @@
 void UndefinedArgChecker::PreVisitObjCMessageExpr(CheckerContext &C,
                                                   const ObjCMessageExpr *ME) {
 
-  // Check for any arguments that are uninitialized/undefined.
   const GRState *state = C.getState();
+
+  if (const Expr *receiver = ME->getReceiver())
+    if (state->getSVal(receiver).isUndef()) {
+      if (ExplodedNode *N = C.GenerateNode(ME, true)) {
+        if (!BT_msg_undef)
+          BT_msg_undef =
+            new BuiltinBug("Receiver in message expression is a garbage value");
+        EnhancedBugReport *R =
+          new EnhancedBugReport(*BT_msg_undef, BT_msg_undef->getName(), N);
+        R->addRange(receiver->getSourceRange());
+        R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
+                             receiver);
+        C.EmitReport(R);
+      }
+      return;
+    }
+
+  // Check for any arguments that are uninitialized/undefined.
   for (ObjCMessageExpr::const_arg_iterator I = ME->arg_begin(), E = ME->arg_end();
        I != E; ++I) {
     if (state->getSVal(*I).isUndef()) {
       if (ExplodedNode *N = C.GenerateNode(ME, true)) {
-        if (!BT_msg)
-          BT_msg = new BuiltinBug("Pass-by-value argument in message expression"
-                                  " is undefined");      
+        if (!BT_msg_arg)
+          BT_msg_arg =
+            new BuiltinBug("Pass-by-value argument in message expression"
+                           " is undefined");      
         // Generate a report for this bug.
-        EnhancedBugReport *R = new EnhancedBugReport(*BT_msg, BT_msg->getName(),
-                                                     N);
+        EnhancedBugReport *R = new EnhancedBugReport(*BT_msg_arg,
+                                                     BT_msg_arg->getName(), N);
         R->addRange((*I)->getSourceRange());
         R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, *I);
         C.EmitReport(R);
diff --git a/test/Analysis/uninit-msg-expr.m b/test/Analysis/uninit-msg-expr.m
index c2b7366..46e441f 100644
--- a/test/Analysis/uninit-msg-expr.m
+++ b/test/Analysis/uninit-msg-expr.m
@@ -42,7 +42,7 @@
 
 unsigned f1() {
   NSString *aString;
-  return [aString length]; // expected-warning {{Receiver in message expression is an uninitialized value}}
+  return [aString length]; // expected-warning {{Receiver in message expression is a garbage value}}
 }
 
 unsigned f2() {
diff --git a/test/Analysis/uninit-ps-rdar6145427.m b/test/Analysis/uninit-ps-rdar6145427.m
index d9e7318..7be32b4 100644
--- a/test/Analysis/uninit-ps-rdar6145427.m
+++ b/test/Analysis/uninit-ps-rdar6145427.m
@@ -30,7 +30,7 @@
 
 int main (int argc, const char * argv[]) {
   NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
-  id someUnintializedPointer = [someUnintializedPointer objectAtIndex:0]; // expected-warning{{Receiver in message expression is an uninitialized value.}}
+  id someUnintializedPointer = [someUnintializedPointer objectAtIndex:0]; // expected-warning{{Receiver in message expression is a garbage value}}
   NSLog(@"%@", someUnintializedPointer);    
   [pool drain];
   return 0;