[analyzer] Improve debug output for PathDiagnosticPieces.

You can now dump a single PathDiagnosticPiece or PathDiagnosticLocation.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@183367 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
index cae47f8..abcd13d 100644
--- a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
+++ b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
@@ -285,6 +285,8 @@
   
   void Profile(llvm::FoldingSetNodeID &ID) const;
 
+  void dump() const;
+
   /// \brief Given an exploded node, retrieve the statement that should be used 
   /// for the diagnostic location.
   static const Stmt *getStmt(const ExplodedNode *N);
@@ -401,6 +403,8 @@
   bool isLastInMainSourceFile() const {
     return LastInMainSourceFile;
   }
+
+  virtual void dump() const = 0;
 };
   
   
@@ -435,7 +439,7 @@
 
   PathDiagnosticLocation getLocation() const { return Pos; }
   virtual void flattenLocations() { Pos.flatten(); }
-  
+
   virtual void Profile(llvm::FoldingSetNodeID &ID) const;
 
   static bool classof(const PathDiagnosticPiece *P) {
@@ -529,6 +533,8 @@
     return "";  
   }
 
+  virtual void dump() const;
+
   static inline bool classof(const PathDiagnosticPiece *P) {
     return P->getKind() == Event;
   }
@@ -596,6 +602,8 @@
   static PathDiagnosticCallPiece *construct(PathPieces &pieces,
                                             const Decl *caller);
   
+  virtual void dump() const;
+
   virtual void Profile(llvm::FoldingSetNodeID &ID) const;
 
   static inline bool classof(const PathDiagnosticPiece *P) {
@@ -663,7 +671,9 @@
   static inline bool classof(const PathDiagnosticPiece *P) {
     return P->getKind() == ControlFlow;
   }
-  
+
+  virtual void dump() const;
+
   virtual void Profile(llvm::FoldingSetNodeID &ID) const;
 };
 
@@ -687,7 +697,9 @@
   static inline bool classof(const PathDiagnosticPiece *P) {
     return P->getKind() == Macro;
   }
-  
+
+  virtual void dump() const;
+
   virtual void Profile(llvm::FoldingSetNodeID &ID) const;
 };
 
diff --git a/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp
index 15073bb6..829e748 100644
--- a/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ b/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -1886,60 +1886,6 @@
 typedef llvm::DenseSet<const PathDiagnosticCallPiece *>
         OptimizedCallsSet;
 
-void PathPieces::dump() const {
-  unsigned index = 0;
-  for (PathPieces::const_iterator I = begin(), E = end(); I != E; ++I ) {
-    llvm::errs() << "[" << index++ << "]";
-
-    switch ((*I)->getKind()) {
-    case PathDiagnosticPiece::Call:
-      llvm::errs() << "  CALL\n--------------\n";
-
-      if (const Stmt *SLoc = getLocStmt((*I)->getLocation())) {
-        SLoc->dump();
-      } else {
-        const PathDiagnosticCallPiece *Call = cast<PathDiagnosticCallPiece>(*I);
-        if (const NamedDecl *ND = dyn_cast<NamedDecl>(Call->getCallee()))
-          llvm::errs() << *ND << "\n";
-      }
-      break;
-    case PathDiagnosticPiece::Event:
-      llvm::errs() << "  EVENT\n--------------\n";
-      llvm::errs() << (*I)->getString() << "\n";
-      if (const Stmt *SLoc = getLocStmt((*I)->getLocation())) {
-        llvm::errs() << " ---- at ----\n";
-        SLoc->dump();
-      }
-      break;
-    case PathDiagnosticPiece::Macro:
-      llvm::errs() << "  MACRO\n--------------\n";
-      // FIXME: print which macro is being invoked.
-      break;
-    case PathDiagnosticPiece::ControlFlow: {
-      const PathDiagnosticControlFlowPiece *CP =
-        cast<PathDiagnosticControlFlowPiece>(*I);
-      llvm::errs() << "  CONTROL\n--------------\n";
-
-      if (const Stmt *s1Start = getLocStmt(CP->getStartLocation()))
-        s1Start->dump();
-      else
-        llvm::errs() << "NULL\n";
-
-      llvm::errs() << " ---- to ----\n";
-
-      if (const Stmt *s1End = getLocStmt(CP->getEndLocation()))
-        s1End->dump();
-      else
-        llvm::errs() << "NULL\n";
-
-      break;
-    }
-    }
-
-    llvm::errs() << "\n";
-  }
-}
-
 /// Adds synthetic edges from top-level statements to their subexpressions.
 ///
 /// This avoids a "swoosh" effect, where an edge from a top-level statement A
@@ -3448,3 +3394,78 @@
   }
   return BT;
 }
+
+
+void PathPieces::dump() const {
+  unsigned index = 0;
+  for (PathPieces::const_iterator I = begin(), E = end(); I != E; ++I) {
+    llvm::errs() << "[" << index++ << "]  ";
+    (*I)->dump();
+    llvm::errs() << "\n";
+  }
+}
+
+void PathDiagnosticCallPiece::dump() const {
+  llvm::errs() << "CALL\n--------------\n";
+
+  if (const Stmt *SLoc = getLocStmt(getLocation()))
+    SLoc->dump();
+  else if (const NamedDecl *ND = dyn_cast<NamedDecl>(getCallee()))
+    llvm::errs() << *ND << "\n";
+  else
+    getLocation().dump();
+}
+
+void PathDiagnosticEventPiece::dump() const {
+  llvm::errs() << "EVENT\n--------------\n";
+  llvm::errs() << getString() << "\n";
+  llvm::errs() << " ---- at ----\n";
+  getLocation().dump();
+}
+
+void PathDiagnosticControlFlowPiece::dump() const {
+  llvm::errs() << "CONTROL\n--------------\n";
+  getStartLocation().dump();
+  llvm::errs() << " ---- to ----\n";
+  getEndLocation().dump();
+}
+
+void PathDiagnosticMacroPiece::dump() const {
+  llvm::errs() << "MACRO\n--------------\n";
+  // FIXME: Print which macro is being invoked.
+}
+
+void PathDiagnosticLocation::dump() const {
+  if (!isValid()) {
+    llvm::errs() << "<INVALID>\n";
+    return;
+  }
+
+  switch (K) {
+  case RangeK:
+    // FIXME: actually print the range.
+    llvm::errs() << "<range>\n";
+    break;
+  case SingleLocK:
+    asLocation().dump();
+    llvm::errs() << "\n";
+    break;
+  case StmtK:
+    if (S)
+      S->dump();
+    else
+      llvm::errs() << "<NULL STMT>\n";
+    break;
+  case DeclK:
+    if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(D))
+      llvm::errs() << *ND << "\n";
+    else if (isa<BlockDecl>(D))
+      // FIXME: Make this nicer.
+      llvm::errs() << "<block>\n";
+    else if (D)
+      llvm::errs() << "<unknown decl>\n";
+    else
+      llvm::errs() << "<NULL DECL>\n";
+    break;
+  }
+}