Static Analyzer Diagnostics: Kill the addVisitorCreator(callbackTy, void*) API in favor of addVisitor(BugReporterVisitor*).

1) Create a header file to expose the predefined visitors. And move the parent(BugReporterVisitor) there as well.

2) Remove the registerXXXVisitor functions - the Visitor constructors/getters can be used now to create the object. One exception is registerVarDeclsLastStore(), which registers more then one visitor, so make it static member of FindLastStoreBRVisitor.

3) Modify all the checkers to use the new API.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@138126 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/StaticAnalyzer/Checkers/AttrNonNullChecker.cpp b/lib/StaticAnalyzer/Checkers/AttrNonNullChecker.cpp
index 285b392..8296eb9 100644
--- a/lib/StaticAnalyzer/Checkers/AttrNonNullChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/AttrNonNullChecker.cpp
@@ -101,15 +101,14 @@
                                "API"));
 
         BugReport *R =
-          new BugReport(*BT,
-                                "Null pointer passed as an argument to a "
-                                "'nonnull' parameter", errorNode);
+          new BugReport(*BT, "Null pointer passed as an argument to a "
+                             "'nonnull' parameter", errorNode);
 
         // Highlight the range of the argument that was null.
         const Expr *arg = *I;
         R->addRange(arg->getSourceRange());
-        R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, arg);
-
+        R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(errorNode,
+                                                                   arg));
         // Emit the bug report.
         C.EmitReport(R);
       }
diff --git a/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp b/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
index da59205..1631df8 100644
--- a/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
+++ b/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
@@ -414,7 +414,7 @@
 
     BugReport *report = new BugReport(*BT, description, N);
     report->addRange(Arg->getSourceRange());
-    report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, Arg);
+    report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, Arg));
     C.EmitReport(report);
     return;
   }
diff --git a/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
index c5d4379..d043e2d 100644
--- a/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
@@ -231,7 +231,7 @@
     BugReport *report = new BugReport(*BT, os.str(), N);
 
     report->addRange(S->getSourceRange());
-    report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, S);
+    report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, S));
     C.EmitReport(report);
     return NULL;
   }
diff --git a/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp b/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
index 191d4bb..ba1dae8 100644
--- a/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
@@ -65,8 +65,8 @@
     return;
 
   BugReport *R = new BugReport(*BT, BT->getName(), N);
-  R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
-                       bugreporter::GetCalleeExpr(N));
+  R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N,
+                               bugreporter::GetCalleeExpr(N)));
   C.EmitReport(R);
 }
 
@@ -95,7 +95,7 @@
       BugReport *R = new BugReport(*BT, BT->getName(), N);
       R->addRange(argRange);
       if (argEx)
-        R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, argEx);
+        R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, argEx));
       C.EmitReport(R);
     }
     return true;
@@ -230,8 +230,8 @@
         BugReport *R =
           new BugReport(*BT_msg_undef, BT_msg_undef->getName(), N);
         R->addRange(receiver->getSourceRange());
-        R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
-                             receiver);
+        R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N,
+                                                                   receiver));
         C.EmitReport(R);
       }
       return;
@@ -275,8 +275,8 @@
   BugReport *report = new BugReport(*BT_msg_ret, os.str(), N);
   if (const Expr *receiver = msg.getInstanceReceiver()) {
     report->addRange(receiver->getSourceRange());
-    report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
-                              receiver);
+    report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N,
+                                                                    receiver));
   }
   C.EmitReport(report);
 }
diff --git a/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp b/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
index 22af688..c416dd8 100644
--- a/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
@@ -75,8 +75,8 @@
 
       BugReport *report =
         new BugReport(*BT_undef, BT_undef->getDescription(), N);
-      report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
-                                bugreporter::GetDerefExpr(N));
+      report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N,
+                                        bugreporter::GetDerefExpr(N)));
       C.EmitReport(report);
     }
     return;
@@ -162,8 +162,8 @@
                               buf.empty() ? BT_null->getDescription():buf.str(),
                               N);
 
-      report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
-                                bugreporter::GetDerefExpr(N));
+      report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N,
+                                        bugreporter::GetDerefExpr(N)));
 
       for (SmallVectorImpl<SourceRange>::iterator
             I = Ranges.begin(), E = Ranges.end(); I!=E; ++I)
diff --git a/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp b/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp
index d87c773..75b7cc4 100644
--- a/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp
@@ -63,8 +63,8 @@
       BugReport *R = 
         new BugReport(*BT, BT->getDescription(), N);
 
-      R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
-                           bugreporter::GetDenomExpr(N));
+      R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N,
+                                   bugreporter::GetDenomExpr(N)));
 
       C.EmitReport(R);
     }
diff --git a/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp b/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp
index af819ec..46f06a0 100644
--- a/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp
@@ -413,12 +413,12 @@
       if (LHSRelevant) {
         const Expr *LHS = i->first->getLHS();
         report->addRange(LHS->getSourceRange());
-        report->addVisitorCreator(bugreporter::registerVarDeclsLastStore, LHS);
+        FindLastStoreBRVisitor::registerStatementVarDecls(*report, LHS);
       }
       if (RHSRelevant) {
         const Expr *RHS = i->first->getRHS();
         report->addRange(i->first->getRHS()->getSourceRange());
-        report->addVisitorCreator(bugreporter::registerVarDeclsLastStore, RHS);
+        FindLastStoreBRVisitor::registerStatementVarDecls(*report, RHS);
       }
 
       BR.EmitReport(report);
diff --git a/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp b/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp
index 7b964a4..3e4e07b 100644
--- a/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp
@@ -49,7 +49,7 @@
                                   "for @synchronized"));
       BugReport *report =
         new BugReport(*BT_undef, BT_undef->getDescription(), N);
-      report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, Ex);
+      report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, Ex));
       C.EmitReport(report);
     }
     return;
@@ -72,8 +72,7 @@
                                    "(no synchronization will occur)"));
         BugReport *report =
           new BugReport(*BT_null, BT_null->getDescription(), N);
-        report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
-                                  Ex);
+        report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, Ex));
 
         C.EmitReport(report);
         return;
diff --git a/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp b/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp
index 979c107..e8c8d90 100644
--- a/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp
@@ -54,7 +54,7 @@
     new BugReport(*BT, BT->getDescription(), N);
 
   report->addRange(RetE->getSourceRange());
-  report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, RetE);
+  report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, RetE));
 
   C.EmitReport(report);
 }
diff --git a/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp b/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp
index f29cac6..de20e89 100644
--- a/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp
@@ -99,8 +99,8 @@
       Ex = FindIt.FindExpr(Ex);
 
       // Emit the bug report.
-      BugReport *R = new BugReport(*BT, BT->getDescription(),N);
-      R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, Ex);
+      BugReport *R = new BugReport(*BT, BT->getDescription(), N);
+      R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, Ex));
       R->addRange(Ex->getSourceRange());
 
       Eng.getBugReporter().EmitReport(R);
diff --git a/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp b/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp
index 486ddbb..2aebed9 100644
--- a/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp
@@ -74,8 +74,9 @@
     // Get the VarRegion associated with VD in the local stack frame.
     const LocationContext *LC = C.getPredecessor()->getLocationContext();
     VR = C.getSValBuilder().getRegionManager().getVarRegion(VD, LC);
+    SVal VRVal = state->getSVal(VR);
 
-    if (state->getSVal(VR).isUndef())
+    if (VRVal.isUndef())
       if (ExplodedNode *N = C.generateSink()) {
         if (!BT)
           BT.reset(new BuiltinBug("uninitialized variable captured by block"));
@@ -90,7 +91,7 @@
         BugReport *R = new BugReport(*BT, os.str(), N);
         if (const Expr *Ex = FindBlockDeclRefExpr(BE->getBody(), VD))
           R->addRange(Ex->getSourceRange());
-        R->addVisitorCreator(bugreporter::registerFindLastStore, VR);
+        R->addVisitor(new FindLastStoreBRVisitor(VRVal, VR));
         // need location of block
         C.EmitReport(R);
       }
diff --git a/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp b/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
index 1074688..7ae9668 100644
--- a/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
@@ -74,10 +74,10 @@
     BugReport *report = new BugReport(*BT, OS.str(), N);
     if (Ex) {
       report->addRange(Ex->getSourceRange());
-      report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, Ex);
+      report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, Ex));
     }
     else
-      report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, B);
+      report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, B));
     C.EmitReport(report);
   }
 }
diff --git a/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp b/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp
index 92e6561..bb6831b 100644
--- a/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp
@@ -42,8 +42,8 @@
       // Generate a report for this bug.
       BugReport *R = new BugReport(*BT, BT->getName(), N);
       R->addRange(A->getIdx()->getSourceRange());
-      R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, 
-                           A->getIdx());
+      R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N,
+                                                                 A->getIdx()));
       C.EmitReport(R);
     }
   }
diff --git a/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp b/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp
index 6f937c6..b0c4bee 100644
--- a/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp
@@ -77,7 +77,7 @@
   BugReport *R = new BugReport(*BT, str, N);
   if (ex) {
     R->addRange(ex->getSourceRange());
-    R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, ex);
+    R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, ex));
   }
   C.EmitReport(R);
 }
diff --git a/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp b/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
index f6931fc..336df59 100644
--- a/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
@@ -206,8 +206,8 @@
       new BugReport(*BT_mallocZero, "Call to 'malloc' has an allocation"
                                             " size of 0 bytes", N);
     report->addRange(CE->getArg(0)->getSourceRange());
-    report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
-                              CE->getArg(0));
+    report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N,
+                                                                CE->getArg(0)));
     C.EmitReport(report);
     return;
   }
diff --git a/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp b/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp
index 61590b2..b34b97c 100644
--- a/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp
@@ -65,7 +65,7 @@
     BugReport *report =
       new BugReport(*BT_undef, BT_undef->getName(), N);
     report->addRange(SE->getSourceRange());
-    report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, SE);
+    report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, SE));
     C.EmitReport(report);
     return;
   }
@@ -90,7 +90,7 @@
     BugReport *report =
       new BugReport(*BT_zero, BT_zero->getName(), N);
     report->addRange(SE->getSourceRange());
-    report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, SE);
+    report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, SE));
     C.EmitReport(report);
     return;
   }
diff --git a/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp
index 6821806..fb0331c 100644
--- a/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ b/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -1672,8 +1672,8 @@
     return;
 
   // Register additional node visitors.
-  bugreporter::registerNilReceiverVisitor(*R);
-  bugreporter::registerConditionVisitor(*R);
+  R->addVisitor(new NilReceiverBRVisitor());
+  R->addVisitor(new ConditionBRVisitor());
 
   switch (PDB.getGenerationScheme()) {
     case PathDiagnosticClient::Extensive:
diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
index b6e726f..9fbccf8 100644
--- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -11,6 +11,7 @@
 //  enhance the diagnostics reported for a bug.
 //
 //===----------------------------------------------------------------------===//
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h"
 
 #include "clang/AST/Expr.h"
 #include "clang/AST/ExprObjC.h"
@@ -71,134 +72,183 @@
 //===----------------------------------------------------------------------===//
 // Definitions for bug reporter visitors.
 //===----------------------------------------------------------------------===//
+void FindLastStoreBRVisitor ::Profile(llvm::FoldingSetNodeID &ID) const {
+  static int tag = 0;
+  ID.AddPointer(&tag);
+  ID.AddPointer(R);
+  ID.Add(V);
+}
 
-namespace {
-class FindLastStoreBRVisitor : public BugReporterVisitor {
-  const MemRegion *R;
-  SVal V;
-  bool satisfied;
-  const ExplodedNode *StoreSite;
-public:
-  FindLastStoreBRVisitor(SVal v, const MemRegion *r)
-  : R(r), V(v), satisfied(false), StoreSite(0) {}
+PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *N,
+                                                     const ExplodedNode *PrevN,
+                                                     BugReporterContext &BRC,
+                                                     BugReport &BR) {
 
-  virtual void Profile(llvm::FoldingSetNodeID &ID) const {
-    static int tag = 0;
-    ID.AddPointer(&tag);
-    ID.AddPointer(R);
-    ID.Add(V);
+  if (satisfied)
+    return NULL;
+
+  if (!StoreSite) {
+    const ExplodedNode *Node = N, *Last = NULL;
+
+    for ( ; Node ; Last = Node, Node = Node->getFirstPred()) {
+
+      if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
+        if (const PostStmt *P = Node->getLocationAs<PostStmt>())
+          if (const DeclStmt *DS = P->getStmtAs<DeclStmt>())
+            if (DS->getSingleDecl() == VR->getDecl()) {
+              Last = Node;
+              break;
+            }
+      }
+
+      if (Node->getState()->getSVal(R) != V)
+        break;
+    }
+
+    if (!Node || !Last) {
+      satisfied = true;
+      return NULL;
+    }
+
+    StoreSite = Last;
   }
 
-  PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
-                                 const ExplodedNode *PrevN,
-                                 BugReporterContext &BRC,
-                                 BugReport &BR) {
+  if (StoreSite != N)
+    return NULL;
 
-    if (satisfied)
-      return NULL;
+  satisfied = true;
+  llvm::SmallString<256> sbuf;
+  llvm::raw_svector_ostream os(sbuf);
 
-    if (!StoreSite) {
-      const ExplodedNode *Node = N, *Last = NULL;
+  if (const PostStmt *PS = N->getLocationAs<PostStmt>()) {
+    if (const DeclStmt *DS = PS->getStmtAs<DeclStmt>()) {
 
-      for ( ; Node ; Last = Node, Node = Node->getFirstPred()) {
-
-        if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
-          if (const PostStmt *P = Node->getLocationAs<PostStmt>())
-            if (const DeclStmt *DS = P->getStmtAs<DeclStmt>())
-              if (DS->getSingleDecl() == VR->getDecl()) {
-                Last = Node;
-                break;
-              }
-        }
-
-        if (Node->getState()->getSVal(R) != V)
-          break;
+      if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
+        os << "Variable '" << VR->getDecl() << "' ";
       }
-
-      if (!Node || !Last) {
-        satisfied = true;
+      else
         return NULL;
-      }
 
-      StoreSite = Last;
-    }
-
-    if (StoreSite != N)
-      return NULL;
-
-    satisfied = true;
-    llvm::SmallString<256> sbuf;
-    llvm::raw_svector_ostream os(sbuf);
-
-    if (const PostStmt *PS = N->getLocationAs<PostStmt>()) {
-      if (const DeclStmt *DS = PS->getStmtAs<DeclStmt>()) {
-
-        if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
-          os << "Variable '" << VR->getDecl() << "' ";
-        }
-        else
-          return NULL;
-
-        if (isa<loc::ConcreteInt>(V)) {
-          bool b = false;
-          if (R->isBoundable()) {
-            if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) {
-              if (TR->getValueType()->isObjCObjectPointerType()) {
-                os << "initialized to nil";
-                b = true;
-              }
-            }
-          }
-
-          if (!b)
-            os << "initialized to a null pointer value";
-        }
-        else if (isa<nonloc::ConcreteInt>(V)) {
-          os << "initialized to " << cast<nonloc::ConcreteInt>(V).getValue();
-        }
-        else if (V.isUndef()) {
-          if (isa<VarRegion>(R)) {
-            const VarDecl *VD = cast<VarDecl>(DS->getSingleDecl());
-            if (VD->getInit())
-              os << "initialized to a garbage value";
-            else
-              os << "declared without an initial value";
-          }
-        }
-      }
-    }
-
-    if (os.str().empty()) {
       if (isa<loc::ConcreteInt>(V)) {
         bool b = false;
         if (R->isBoundable()) {
           if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) {
             if (TR->getValueType()->isObjCObjectPointerType()) {
-              os << "nil object reference stored to ";
+              os << "initialized to nil";
               b = true;
             }
           }
         }
 
         if (!b)
-          os << "Null pointer value stored to ";
-      }
-      else if (V.isUndef()) {
-        os << "Uninitialized value stored to ";
+          os << "initialized to a null pointer value";
       }
       else if (isa<nonloc::ConcreteInt>(V)) {
-        os << "The value " << cast<nonloc::ConcreteInt>(V).getValue()
-           << " is assigned to ";
+        os << "initialized to " << cast<nonloc::ConcreteInt>(V).getValue();
       }
-      else
-        return NULL;
-
-      if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
-        os << '\'' << VR->getDecl() << '\'';
+      else if (V.isUndef()) {
+        if (isa<VarRegion>(R)) {
+          const VarDecl *VD = cast<VarDecl>(DS->getSingleDecl());
+          if (VD->getInit())
+            os << "initialized to a garbage value";
+          else
+            os << "declared without an initial value";
+        }
       }
-      else
-        return NULL;
     }
+  }
+
+  if (os.str().empty()) {
+    if (isa<loc::ConcreteInt>(V)) {
+      bool b = false;
+      if (R->isBoundable()) {
+        if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) {
+          if (TR->getValueType()->isObjCObjectPointerType()) {
+            os << "nil object reference stored to ";
+            b = true;
+          }
+        }
+      }
+
+      if (!b)
+        os << "Null pointer value stored to ";
+    }
+    else if (V.isUndef()) {
+      os << "Uninitialized value stored to ";
+    }
+    else if (isa<nonloc::ConcreteInt>(V)) {
+      os << "The value " << cast<nonloc::ConcreteInt>(V).getValue()
+               << " is assigned to ";
+    }
+    else
+      return NULL;
+
+    if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
+      os << '\'' << VR->getDecl() << '\'';
+    }
+    else
+      return NULL;
+  }
+
+  // FIXME: Refactor this into BugReporterContext.
+  const Stmt *S = 0;
+  ProgramPoint P = N->getLocation();
+
+  if (BlockEdge *BE = dyn_cast<BlockEdge>(&P)) {
+    const CFGBlock *BSrc = BE->getSrc();
+    S = BSrc->getTerminatorCondition();
+  }
+  else if (PostStmt *PS = dyn_cast<PostStmt>(&P)) {
+    S = PS->getStmt();
+  }
+
+  if (!S)
+    return NULL;
+
+  // Construct a new PathDiagnosticPiece.
+  PathDiagnosticLocation L(S, BRC.getSourceManager());
+  return new PathDiagnosticEventPiece(L, os.str());
+}
+
+void TrackConstraintBRVisitor::Profile(llvm::FoldingSetNodeID &ID) const {
+  static int tag = 0;
+  ID.AddPointer(&tag);
+  ID.AddBoolean(Assumption);
+  ID.Add(Constraint);
+}
+
+PathDiagnosticPiece *
+TrackConstraintBRVisitor::VisitNode(const ExplodedNode *N,
+                                    const ExplodedNode *PrevN,
+                                    BugReporterContext &BRC,
+                                    BugReport &BR) {
+  if (isSatisfied)
+    return NULL;
+
+  // Check if in the previous state it was feasible for this constraint
+  // to *not* be true.
+  if (PrevN->getState()->assume(Constraint, !Assumption)) {
+
+    isSatisfied = true;
+
+    // As a sanity check, make sure that the negation of the constraint
+    // was infeasible in the current state.  If it is feasible, we somehow
+    // missed the transition point.
+    if (N->getState()->assume(Constraint, !Assumption))
+      return NULL;
+
+    // We found the transition point for the constraint.  We now need to
+    // pretty-print the constraint. (work-in-progress)
+    std::string sbuf;
+    llvm::raw_string_ostream os(sbuf);
+
+    if (isa<Loc>(Constraint)) {
+      os << "Assuming pointer value is ";
+      os << (Assumption ? "non-null" : "null");
+    }
+
+    if (os.str().empty())
+      return NULL;
 
     // FIXME: Refactor this into BugReporterContext.
     const Stmt *S = 0;
@@ -219,101 +269,16 @@
     PathDiagnosticLocation L(S, BRC.getSourceManager());
     return new PathDiagnosticEventPiece(L, os.str());
   }
-};
 
-
-static void registerFindLastStore(BugReport &BR, const MemRegion *R,
-                                  SVal V) {
-  BR.addVisitor(new FindLastStoreBRVisitor(V, R));
+  return NULL;
 }
 
-class TrackConstraintBRVisitor : public BugReporterVisitor {
-  DefinedSVal Constraint;
-  const bool Assumption;
-  bool isSatisfied;
-public:
-  TrackConstraintBRVisitor(DefinedSVal constraint, bool assumption)
-  : Constraint(constraint), Assumption(assumption), isSatisfied(false) {}
+BugReporterVisitor *
+bugreporter::getTrackNullOrUndefValueVisitor(const ExplodedNode *N,
+                                             const Stmt *S) {
+  if (!S || !N)
+    return 0;
 
-  void Profile(llvm::FoldingSetNodeID &ID) const {
-    static int tag = 0;
-    ID.AddPointer(&tag);
-    ID.AddBoolean(Assumption);
-    ID.Add(Constraint);
-  }
-
-  PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
-                                 const ExplodedNode *PrevN,
-                                 BugReporterContext &BRC,
-                                 BugReport &BR) {
-    if (isSatisfied)
-      return NULL;
-
-    // Check if in the previous state it was feasible for this constraint
-    // to *not* be true.
-    if (PrevN->getState()->assume(Constraint, !Assumption)) {
-
-      isSatisfied = true;
-
-      // As a sanity check, make sure that the negation of the constraint
-      // was infeasible in the current state.  If it is feasible, we somehow
-      // missed the transition point.
-      if (N->getState()->assume(Constraint, !Assumption))
-        return NULL;
-
-      // We found the transition point for the constraint.  We now need to
-      // pretty-print the constraint. (work-in-progress)
-      std::string sbuf;
-      llvm::raw_string_ostream os(sbuf);
-
-      if (isa<Loc>(Constraint)) {
-        os << "Assuming pointer value is ";
-        os << (Assumption ? "non-null" : "null");
-      }
-
-      if (os.str().empty())
-        return NULL;
-
-      // FIXME: Refactor this into BugReporterContext.
-      const Stmt *S = 0;
-      ProgramPoint P = N->getLocation();
-
-      if (BlockEdge *BE = dyn_cast<BlockEdge>(&P)) {
-        const CFGBlock *BSrc = BE->getSrc();
-        S = BSrc->getTerminatorCondition();
-      }
-      else if (PostStmt *PS = dyn_cast<PostStmt>(&P)) {
-        S = PS->getStmt();
-      }
-
-      if (!S)
-        return NULL;
-
-      // Construct a new PathDiagnosticPiece.
-      PathDiagnosticLocation L(S, BRC.getSourceManager());
-      return new PathDiagnosticEventPiece(L, os.str());
-    }
-
-    return NULL;
-  }
-};
-} // end anonymous namespace
-
-static void registerTrackConstraint(BugReport &BR,
-                                    DefinedSVal Constraint,
-                                    bool Assumption) {
-  BR.addVisitor(new TrackConstraintBRVisitor(Constraint, Assumption));
-}
-
-void bugreporter::registerTrackNullOrUndefValue(BugReport &BR,
-                                                const void *data) {
-
-  const Stmt *S = static_cast<const Stmt*>(data);
-  const ExplodedNode *N = BR.getErrorNode();
-
-  if (!S)
-    return;
-  
   ProgramStateManager &StateMgr = N->getState()->getStateManager();
 
   // Walk through nodes until we get one that matches the statement
@@ -328,7 +293,7 @@
   }
 
   if (!N)
-    return;
+    return 0;
   
   const ProgramState *state = N->getState();
 
@@ -343,7 +308,7 @@
 
       if (isa<loc::ConcreteInt>(V) || isa<nonloc::ConcreteInt>(V)
           || V.isUndef()) {
-        ::registerFindLastStore(BR, R, V);
+        return new FindLastStoreBRVisitor(V, R);
       }
     }
   }
@@ -363,87 +328,64 @@
 
     if (R) {
       assert(isa<SymbolicRegion>(R));
-      registerTrackConstraint(BR, loc::MemRegionVal(R), false);
+      return new TrackConstraintBRVisitor(loc::MemRegionVal(R), false);
     }
   }
+
+  return 0;
 }
 
-void bugreporter::registerFindLastStore(BugReport &BR,
-                                        const void *data) {
-
-  const MemRegion *R = static_cast<const MemRegion*>(data);
-  const ExplodedNode *N = BR.getErrorNode();
-
-  if (!R)
-    return;
+BugReporterVisitor *
+FindLastStoreBRVisitor::createVisitorObject(const ExplodedNode *N,
+                                            const MemRegion *R) {
+  assert(R && "The memory region is null.");
 
   const ProgramState *state = N->getState();
   SVal V = state->getSVal(R);
-
   if (V.isUnknown())
-    return;
+    return 0;
 
-  BR.addVisitor(new FindLastStoreBRVisitor(V, R));
+  return new FindLastStoreBRVisitor(V, R);
 }
 
 
-namespace {
-class NilReceiverVisitor : public BugReporterVisitor {
-public:
-  NilReceiverVisitor() {}
+PathDiagnosticPiece *NilReceiverBRVisitor::VisitNode(const ExplodedNode *N,
+                                                     const ExplodedNode *PrevN,
+                                                     BugReporterContext &BRC,
+                                                     BugReport &BR) {
+  const PostStmt *P = N->getLocationAs<PostStmt>();
+  if (!P)
+    return 0;
+  const ObjCMessageExpr *ME = P->getStmtAs<ObjCMessageExpr>();
+  if (!ME)
+    return 0;
+  const Expr *Receiver = ME->getInstanceReceiver();
+  if (!Receiver)
+    return 0;
+  const ProgramState *state = N->getState();
+  const SVal &V = state->getSVal(Receiver);
+  const DefinedOrUnknownSVal *DV = dyn_cast<DefinedOrUnknownSVal>(&V);
+  if (!DV)
+    return 0;
+  state = state->assume(*DV, true);
+  if (state)
+    return 0;
 
-  void Profile(llvm::FoldingSetNodeID &ID) const {
-    static int x = 0;
-    ID.AddPointer(&x);
-  }
-
-  PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
-                                 const ExplodedNode *PrevN,
-                                 BugReporterContext &BRC,
-                                 BugReport &BR) {
-
-    const PostStmt *P = N->getLocationAs<PostStmt>();
-    if (!P)
-      return 0;
-    const ObjCMessageExpr *ME = P->getStmtAs<ObjCMessageExpr>();
-    if (!ME)
-      return 0;
-    const Expr *Receiver = ME->getInstanceReceiver();
-    if (!Receiver)
-      return 0;
-    const ProgramState *state = N->getState();
-    const SVal &V = state->getSVal(Receiver);
-    const DefinedOrUnknownSVal *DV = dyn_cast<DefinedOrUnknownSVal>(&V);
-    if (!DV)
-      return 0;
-    state = state->assume(*DV, true);
-    if (state)
-      return 0;
-
-    // The receiver was nil, and hence the method was skipped.
-    // Register a BugReporterVisitor to issue a message telling us how
-    // the receiver was null.
-    bugreporter::registerTrackNullOrUndefValue(BR, Receiver);
-    // Issue a message saying that the method was skipped.
-    PathDiagnosticLocation L(Receiver, BRC.getSourceManager());
-    return new PathDiagnosticEventPiece(L, "No method actually called "
-                                           "because the receiver is nil");
-  }
-};
-} // end anonymous namespace
-
-void bugreporter::registerNilReceiverVisitor(BugReport &BR) {
-  BR.addVisitor(new NilReceiverVisitor());
+  // The receiver was nil, and hence the method was skipped.
+  // Register a BugReporterVisitor to issue a message telling us how
+  // the receiver was null.
+  BR.addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, Receiver));
+  // Issue a message saying that the method was skipped.
+  PathDiagnosticLocation L(Receiver, BRC.getSourceManager());
+  return new PathDiagnosticEventPiece(L, "No method actually called "
+      "because the receiver is nil");
 }
 
 // Registers every VarDecl inside a Stmt with a last store visitor.
-void bugreporter::registerVarDeclsLastStore(BugReport &BR,
-                                            const void *stmt) {
-  const Stmt *S = static_cast<const Stmt *>(stmt);
+void FindLastStoreBRVisitor::registerStatementVarDecls(BugReport &BR,
+                                                       const Stmt *S) {
   const ExplodedNode *N = BR.getErrorNode();
-
   std::deque<const Stmt *> WorkList;
-
   WorkList.push_back(S);
 
   while (!WorkList.empty()) {
@@ -462,7 +404,8 @@
         SVal V = state->getSVal(S);
 
         if (isa<loc::ConcreteInt>(V) || isa<nonloc::ConcreteInt>(V)) {
-          ::registerFindLastStore(BR, R, V);
+          // Register a new visitor with the BugReport.
+          BR.addVisitor(new FindLastStoreBRVisitor(V, R));
         }
       }
     }
@@ -476,51 +419,10 @@
 //===----------------------------------------------------------------------===//
 // Visitor that tries to report interesting diagnostics from conditions.
 //===----------------------------------------------------------------------===//
-
-namespace {
-class ConditionVisitor : public BugReporterVisitor {
-public:
-  void Profile(llvm::FoldingSetNodeID &ID) const {
-    static int x = 0;
-    ID.AddPointer(&x);
-  }
-
-  virtual PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
-                                         const ExplodedNode *Prev,
-                                         BugReporterContext &BRC,
-                                         BugReport &BR);
-  
-  PathDiagnosticPiece *VisitTerminator(const Stmt *Term,
-                                       const ProgramState *CurrentState,
-                                       const ProgramState *PrevState,
-                                       const CFGBlock *srcBlk,
-                                       const CFGBlock *dstBlk,
-                                       BugReporterContext &BRC);
-  
-  PathDiagnosticPiece *VisitTrueTest(const Expr *Cond,
-                                     bool tookTrue,
-                                     BugReporterContext &BRC);
-
-  PathDiagnosticPiece *VisitTrueTest(const Expr *Cond,
-                                     const DeclRefExpr *DR,
-                                     const bool tookTrue,
-                                     BugReporterContext &BRC);
-  
-  PathDiagnosticPiece *VisitTrueTest(const Expr *Cond,
-                                     const BinaryOperator *BExpr,
-                                     const bool tookTrue,
-                                     BugReporterContext &BRC);
-  
-  bool patternMatch(const Expr *Ex,
-                    llvm::raw_ostream &Out,
-                    BugReporterContext &BRC);
-};
-}
-
-PathDiagnosticPiece *ConditionVisitor::VisitNode(const ExplodedNode *N,
-                                                 const ExplodedNode *Prev,
-                                                 BugReporterContext &BRC,
-                                                 BugReport &BR) {
+PathDiagnosticPiece *ConditionBRVisitor::VisitNode(const ExplodedNode *N,
+                                                   const ExplodedNode *Prev,
+                                                   BugReporterContext &BRC,
+                                                   BugReport &BR) {
   
   const ProgramPoint &progPoint = N->getLocation();
 
@@ -564,13 +466,12 @@
 }
 
 PathDiagnosticPiece *
-ConditionVisitor::VisitTerminator(const Stmt *Term,
-                                  const ProgramState *CurrentState,
-                                  const ProgramState *PrevState,
-                                  const CFGBlock *srcBlk,
-                                  const CFGBlock *dstBlk,
-                                  BugReporterContext &BRC) {
-
+ConditionBRVisitor::VisitTerminator(const Stmt *Term,
+                                    const ProgramState *CurrentState,
+                                    const ProgramState *PrevState,
+                                    const CFGBlock *srcBlk,
+                                    const CFGBlock *dstBlk,
+                                    BugReporterContext &BRC) {
   const Expr *Cond = 0;
   
   switch (Term->getStmtClass()) {
@@ -592,9 +493,9 @@
 }
 
 PathDiagnosticPiece *
-ConditionVisitor::VisitTrueTest(const Expr *Cond,
-                                bool tookTrue,
-                                BugReporterContext &BRC) {
+ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
+                                  bool tookTrue,
+                                  BugReporterContext &BRC) {
   
   const Expr *Ex = Cond;
   
@@ -620,8 +521,8 @@
   }
 }
 
-bool ConditionVisitor::patternMatch(const Expr *Ex, llvm::raw_ostream &Out,
-                                    BugReporterContext &BRC) {
+bool ConditionBRVisitor::patternMatch(const Expr *Ex, llvm::raw_ostream &Out,
+                                      BugReporterContext &BRC) {
   const Expr *OriginalExpr = Ex;
   Ex = Ex->IgnoreParenCasts();
 
@@ -658,10 +559,10 @@
 }
 
 PathDiagnosticPiece *
-ConditionVisitor::VisitTrueTest(const Expr *Cond,
-                                const BinaryOperator *BExpr,
-                                const bool tookTrue,
-                                BugReporterContext &BRC) {
+ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
+                                  const BinaryOperator *BExpr,
+                                  const bool tookTrue,
+                                  BugReporterContext &BRC) {
   
   bool shouldInvert = false;
   
@@ -726,10 +627,10 @@
 }
   
 PathDiagnosticPiece *
-ConditionVisitor::VisitTrueTest(const Expr *Cond,
-                                const DeclRefExpr *DR,
-                                const bool tookTrue,
-                                BugReporterContext &BRC) {
+ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
+                                  const DeclRefExpr *DR,
+                                  const bool tookTrue,
+                                  BugReporterContext &BRC) {
 
   const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl());
   if (!VD)
@@ -756,8 +657,3 @@
   PathDiagnosticLocation Loc(Cond, BRC.getSourceManager());
   return new PathDiagnosticEventPiece(Loc, Out.str());
 }
-
-void bugreporter::registerConditionVisitor(BugReport &BR) {
-  BR.addVisitor(new ConditionVisitor());
-}
-