[AST] Extract ASTNodeTraverser class from ASTDumper

Summary:
This new traverser class allows clients to re-use the traversal logic
which was previously part of ASTDumper.  This means that alternative
visit logic may be implemented, such as

* Dump to alternative data formats such as JSON
* Implement AST Matcher parent/child visitation matching AST dumps

Reviewers: aaron.ballman

Subscribers: jfb, cfe-commits

Differential Revision: https://reviews.llvm.org/D57472

llvm-svn: 352989
diff --git a/clang/lib/AST/ASTDumper.cpp b/clang/lib/AST/ASTDumper.cpp
index e539290..f893851 100644
--- a/clang/lib/AST/ASTDumper.cpp
+++ b/clang/lib/AST/ASTDumper.cpp
@@ -12,20 +12,9 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/AST/ASTContext.h"
-#include "clang/AST/ASTDumperUtils.h"
-#include "clang/AST/Attr.h"
-#include "clang/AST/AttrVisitor.h"
-#include "clang/AST/CommentVisitor.h"
-#include "clang/AST/DeclCXX.h"
+#include "clang/AST/ASTNodeTraverser.h"
 #include "clang/AST/DeclLookups.h"
-#include "clang/AST/DeclObjC.h"
-#include "clang/AST/DeclOpenMP.h"
-#include "clang/AST/DeclVisitor.h"
-#include "clang/AST/LocInfoType.h"
-#include "clang/AST/StmtVisitor.h"
-#include "clang/AST/TemplateArgumentVisitor.h"
 #include "clang/AST/TextNodeDumper.h"
-#include "clang/AST/TypeVisitor.h"
 #include "clang/Basic/Builtins.h"
 #include "clang/Basic/Module.h"
 #include "clang/Basic/SourceManager.h"
@@ -39,562 +28,44 @@
 
 namespace  {
 
-  class ASTDumper
-      : public ConstDeclVisitor<ASTDumper>,
-        public ConstStmtVisitor<ASTDumper>,
-        public ConstCommentVisitor<ASTDumper, void, const FullComment *>,
-        public TypeVisitor<ASTDumper>,
-        public ConstAttrVisitor<ASTDumper>,
-        public ConstTemplateArgumentVisitor<ASTDumper> {
+class ASTDumper : public ASTNodeTraverser<ASTDumper, TextNodeDumper> {
 
-    TextNodeDumper NodeDumper;
+  TextNodeDumper NodeDumper;
 
-    raw_ostream &OS;
+  raw_ostream &OS;
 
-    /// Indicates whether we should trigger deserialization of nodes that had
-    /// not already been loaded.
-    bool Deserialize = false;
+  const bool ShowColors;
 
-    const bool ShowColors;
+public:
+  ASTDumper(raw_ostream &OS, const CommandTraits *Traits,
+            const SourceManager *SM)
+      : ASTDumper(OS, Traits, SM, SM && SM->getDiagnostics().getShowColors()) {}
 
-  public:
-    ASTDumper(raw_ostream &OS, const CommandTraits *Traits,
-              const SourceManager *SM)
-        : ASTDumper(OS, Traits, SM,
-                    SM && SM->getDiagnostics().getShowColors()) {}
+  ASTDumper(raw_ostream &OS, const CommandTraits *Traits,
+            const SourceManager *SM, bool ShowColors)
+      : ASTDumper(OS, Traits, SM, ShowColors, LangOptions()) {}
+  ASTDumper(raw_ostream &OS, const CommandTraits *Traits,
+            const SourceManager *SM, bool ShowColors,
+            const PrintingPolicy &PrintPolicy)
+      : NodeDumper(OS, ShowColors, SM, PrintPolicy, Traits), OS(OS),
+        ShowColors(ShowColors) {}
 
-    ASTDumper(raw_ostream &OS, const CommandTraits *Traits,
-              const SourceManager *SM, bool ShowColors)
-        : ASTDumper(OS, Traits, SM, ShowColors, LangOptions()) {}
-    ASTDumper(raw_ostream &OS, const CommandTraits *Traits,
-              const SourceManager *SM, bool ShowColors,
-              const PrintingPolicy &PrintPolicy)
-        : NodeDumper(OS, ShowColors, SM, PrintPolicy, Traits), OS(OS),
-          ShowColors(ShowColors) {}
+  TextNodeDumper &doGetNodeDelegate() { return NodeDumper; }
 
-    void setDeserialize(bool D) { Deserialize = D; }
+  void dumpLookups(const DeclContext *DC, bool DumpDecls);
 
-    void Visit(const Decl *D) {
-      NodeDumper.AddChild([=] {
-        NodeDumper.Visit(D);
-        if (!D)
-          return;
+  template <typename SpecializationDecl>
+  void dumpTemplateDeclSpecialization(const SpecializationDecl *D,
+                                      bool DumpExplicitInst, bool DumpRefOnly);
+  template <typename TemplateDecl>
+  void dumpTemplateDecl(const TemplateDecl *D, bool DumpExplicitInst);
 
-        ConstDeclVisitor<ASTDumper>::Visit(D);
-
-        for (const auto &A : D->attrs())
-          Visit(A);
-
-        if (const FullComment *Comment =
-                D->getASTContext().getLocalCommentForDeclUncached(D))
-          Visit(Comment, Comment);
-
-        // Decls within functions are visited by the body.
-        if (!isa<FunctionDecl>(*D) && !isa<ObjCMethodDecl>(*D)) {
-          if (const auto *DC = dyn_cast<DeclContext>(D))
-            dumpDeclContext(DC);
-        }
-      });
-    }
-
-    void Visit(const Stmt *S, StringRef Label = {}) {
-      NodeDumper.AddChild(Label, [=] {
-        NodeDumper.Visit(S);
-
-        if (!S) {
-          return;
-        }
-
-        ConstStmtVisitor<ASTDumper>::Visit(S);
-
-        // Some statements have custom mechanisms for dumping their children.
-        if (isa<DeclStmt>(S) || isa<GenericSelectionExpr>(S)) {
-          return;
-        }
-
-        for (const Stmt *SubStmt : S->children())
-          Visit(SubStmt);
-      });
-    }
-
-    void Visit(QualType T) {
-      SplitQualType SQT = T.split();
-      if (!SQT.Quals.hasQualifiers())
-        return Visit(SQT.Ty);
-
-      NodeDumper.AddChild([=] {
-        NodeDumper.Visit(T);
-        Visit(T.split().Ty);
-      });
-    }
-
-    void Visit(const Type *T) {
-      NodeDumper.AddChild([=] {
-        NodeDumper.Visit(T);
-        if (!T)
-          return;
-        TypeVisitor<ASTDumper>::Visit(T);
-
-        QualType SingleStepDesugar =
-            T->getLocallyUnqualifiedSingleStepDesugaredType();
-        if (SingleStepDesugar != QualType(T, 0))
-          Visit(SingleStepDesugar);
-      });
-    }
-
-    void Visit(const Attr *A) {
-      NodeDumper.AddChild([=] {
-        NodeDumper.Visit(A);
-        ConstAttrVisitor<ASTDumper>::Visit(A);
-      });
-    }
-
-    void Visit(const CXXCtorInitializer *Init) {
-      NodeDumper.AddChild([=] {
-        NodeDumper.Visit(Init);
-        Visit(Init->getInit());
-      });
-    }
-
-    void Visit(const TemplateArgument &A, SourceRange R = {},
-               const Decl *From = nullptr, const char *Label = nullptr) {
-      NodeDumper.AddChild([=] {
-        NodeDumper.Visit(A, R, From, Label);
-        ConstTemplateArgumentVisitor<ASTDumper>::Visit(A);
-      });
-    }
-
-    void Visit(const BlockDecl::Capture &C) {
-      NodeDumper.AddChild([=] {
-        NodeDumper.Visit(C);
-        if (C.hasCopyExpr())
-          Visit(C.getCopyExpr());
-      });
-    }
-
-    void Visit(const OMPClause *C) {
-      NodeDumper.AddChild([=] {
-        NodeDumper.Visit(C);
-        for (const auto *S : C->children())
-          Visit(S);
-      });
-    }
-
-    void Visit(const GenericSelectionExpr::ConstAssociation &A) {
-      NodeDumper.AddChild([=] {
-        NodeDumper.Visit(A);
-        if (const TypeSourceInfo *TSI = A.getTypeSourceInfo())
-          Visit(TSI->getType());
-        Visit(A.getAssociationExpr());
-      });
-    }
-
-    void Visit(const Comment *C, const FullComment *FC) {
-      NodeDumper.AddChild([=] {
-        NodeDumper.Visit(C, FC);
-        if (!C) {
-          return;
-        }
-        ConstCommentVisitor<ASTDumper, void, const FullComment *>::visit(C, FC);
-        for (Comment::child_iterator I = C->child_begin(), E = C->child_end();
-             I != E; ++I)
-          Visit(*I, FC);
-      });
-    }
-
-    void dumpDeclContext(const DeclContext *DC);
-    void dumpLookups(const DeclContext *DC, bool DumpDecls);
-
-    void dumpTemplateParameters(const TemplateParameterList *TPL) {
-      if (!TPL)
-        return;
-
-      for (const auto &TP : *TPL)
-        Visit(TP);
-    }
-
-    void dumpTemplateArgumentListInfo(const TemplateArgumentListInfo &TALI) {
-      for (const auto &TA : TALI.arguments())
-        dumpTemplateArgumentLoc(TA);
-    }
-
-    void dumpTemplateArgumentLoc(const TemplateArgumentLoc &A,
-                                 const Decl *From = nullptr,
-                                 const char *Label = nullptr) {
-      Visit(A.getArgument(), A.getSourceRange(), From, Label);
-    }
-
-    void dumpTemplateArgumentList(const TemplateArgumentList &TAL) {
-      for (unsigned i = 0, e = TAL.size(); i < e; ++i)
-        Visit(TAL[i]);
-    }
-
-    void dumpObjCTypeParamList(const ObjCTypeParamList *typeParams) {
-      if (!typeParams)
-        return;
-
-      for (const auto &typeParam : *typeParams) {
-        Visit(typeParam);
-      }
-    }
-
-    void VisitComplexType(const ComplexType *T) { Visit(T->getElementType()); }
-    void VisitLocInfoType(const LocInfoType *T) {
-      Visit(T->getTypeSourceInfo()->getType());
-    }
-    void VisitPointerType(const PointerType *T) { Visit(T->getPointeeType()); }
-    void VisitBlockPointerType(const BlockPointerType *T) {
-      Visit(T->getPointeeType());
-    }
-    void VisitReferenceType(const ReferenceType *T) {
-      Visit(T->getPointeeType());
-    }
-    void VisitMemberPointerType(const MemberPointerType *T) {
-      Visit(T->getClass());
-      Visit(T->getPointeeType());
-    }
-    void VisitArrayType(const ArrayType *T) { Visit(T->getElementType()); }
-    void VisitVariableArrayType(const VariableArrayType *T) {
-      VisitArrayType(T);
-      Visit(T->getSizeExpr());
-    }
-    void VisitDependentSizedArrayType(const DependentSizedArrayType *T) {
-      Visit(T->getElementType());
-      Visit(T->getSizeExpr());
-    }
-    void
-    VisitDependentSizedExtVectorType(const DependentSizedExtVectorType *T) {
-      Visit(T->getElementType());
-      Visit(T->getSizeExpr());
-    }
-    void VisitVectorType(const VectorType *T) { Visit(T->getElementType()); }
-    void VisitFunctionType(const FunctionType *T) { Visit(T->getReturnType()); }
-    void VisitFunctionProtoType(const FunctionProtoType *T) {
-      VisitFunctionType(T);
-      for (const QualType &PT : T->getParamTypes())
-        Visit(PT);
-    }
-    void VisitTypeOfExprType(const TypeOfExprType *T) {
-      Visit(T->getUnderlyingExpr());
-    }
-    void VisitDecltypeType(const DecltypeType *T) {
-      Visit(T->getUnderlyingExpr());
-    }
-    void VisitUnaryTransformType(const UnaryTransformType *T) {
-      Visit(T->getBaseType());
-    }
-    void VisitAttributedType(const AttributedType *T) {
-      // FIXME: AttrKind
-      Visit(T->getModifiedType());
-    }
-    void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) {
-      Visit(T->getReplacedParameter());
-    }
-    void
-    VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T) {
-      Visit(T->getReplacedParameter());
-      Visit(T->getArgumentPack());
-    }
-    void VisitTemplateSpecializationType(const TemplateSpecializationType *T) {
-      for (const auto &Arg : *T)
-        Visit(Arg);
-      if (T->isTypeAlias())
-        Visit(T->getAliasedType());
-    }
-    void VisitObjCObjectPointerType(const ObjCObjectPointerType *T) {
-      Visit(T->getPointeeType());
-    }
-    void VisitAtomicType(const AtomicType *T) { Visit(T->getValueType()); }
-    void VisitPipeType(const PipeType *T) { Visit(T->getElementType()); }
-    void VisitAdjustedType(const AdjustedType *T) {
-      Visit(T->getOriginalType());
-    }
-    void VisitPackExpansionType(const PackExpansionType *T) {
-      if (!T->isSugared())
-        Visit(T->getPattern());
-    }
-    // FIXME: ElaboratedType, DependentNameType,
-    // DependentTemplateSpecializationType, ObjCObjectType
-
-    void VisitTypedefDecl(const TypedefDecl *D) {
-      Visit(D->getUnderlyingType());
-    }
-
-    void VisitEnumConstantDecl(const EnumConstantDecl *D) {
-      if (const Expr *Init = D->getInitExpr())
-        Visit(Init);
-    }
-
-    void VisitFunctionDecl(const FunctionDecl *D) {
-      if (const auto *FTSI = D->getTemplateSpecializationInfo())
-        dumpTemplateArgumentList(*FTSI->TemplateArguments);
-
-      if (D->param_begin())
-        for (const auto *Parameter : D->parameters())
-          Visit(Parameter);
-
-      if (const auto *C = dyn_cast<CXXConstructorDecl>(D))
-        for (const auto *I : C->inits())
-          Visit(I);
-
-      if (D->doesThisDeclarationHaveABody())
-        Visit(D->getBody());
-    }
-
-    void VisitFieldDecl(const FieldDecl *D) {
-      if (D->isBitField())
-        Visit(D->getBitWidth());
-      if (Expr *Init = D->getInClassInitializer())
-        Visit(Init);
-    }
-
-    void VisitVarDecl(const VarDecl *D) {
-      if (D->hasInit())
-        Visit(D->getInit());
-    }
-
-    void VisitDecompositionDecl(const DecompositionDecl *D) {
-      VisitVarDecl(D);
-      for (const auto *B : D->bindings())
-        Visit(B);
-    }
-
-    void VisitBindingDecl(const BindingDecl *D) {
-      if (const auto *E = D->getBinding())
-        Visit(E);
-    }
-
-    void VisitFileScopeAsmDecl(const FileScopeAsmDecl *D) {
-      Visit(D->getAsmString());
-    }
-
-    void VisitCapturedDecl(const CapturedDecl *D) { Visit(D->getBody()); }
-
-    void VisitOMPThreadPrivateDecl(const OMPThreadPrivateDecl *D) {
-      for (const auto *E : D->varlists())
-        Visit(E);
-    }
-
-    void VisitOMPDeclareReductionDecl(const OMPDeclareReductionDecl *D) {
-      Visit(D->getCombiner());
-      if (const auto *Initializer = D->getInitializer())
-        Visit(Initializer);
-    }
-
-    void VisitOMPDeclareMapperDecl(const OMPDeclareMapperDecl *D) {
-      for (const auto *C : D->clauselists())
-        Visit(C);
-    }
-
-    void VisitOMPCapturedExprDecl(const OMPCapturedExprDecl *D) {
-      Visit(D->getInit());
-    }
-
-    template <typename SpecializationDecl>
-    void dumpTemplateDeclSpecialization(const SpecializationDecl *D,
-                                        bool DumpExplicitInst,
-                                        bool DumpRefOnly);
-    template <typename TemplateDecl>
-    void dumpTemplateDecl(const TemplateDecl *D, bool DumpExplicitInst);
-
-    void VisitTypeAliasDecl(const TypeAliasDecl *D) {
-      Visit(D->getUnderlyingType());
-    }
-
-    void VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D) {
-      dumpTemplateParameters(D->getTemplateParameters());
-      Visit(D->getTemplatedDecl());
-    }
-
-    void VisitStaticAssertDecl(const StaticAssertDecl *D) {
-      Visit(D->getAssertExpr());
-      Visit(D->getMessage());
-    }
-    void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D);
-    void VisitClassTemplateDecl(const ClassTemplateDecl *D);
-
-    void VisitClassTemplateSpecializationDecl(
-        const ClassTemplateSpecializationDecl *D) {
-      dumpTemplateArgumentList(D->getTemplateArgs());
-    }
-
-    void VisitClassTemplatePartialSpecializationDecl(
-        const ClassTemplatePartialSpecializationDecl *D) {
-      VisitClassTemplateSpecializationDecl(D);
-      dumpTemplateParameters(D->getTemplateParameters());
-    }
-
-    void VisitClassScopeFunctionSpecializationDecl(
-        const ClassScopeFunctionSpecializationDecl *D) {
-      Visit(D->getSpecialization());
-      if (D->hasExplicitTemplateArgs())
-        dumpTemplateArgumentListInfo(D->templateArgs());
-    }
-    void VisitVarTemplateDecl(const VarTemplateDecl *D);
-
-    void VisitBuiltinTemplateDecl(const BuiltinTemplateDecl *D) {
-      dumpTemplateParameters(D->getTemplateParameters());
-    }
-
-    void
-    VisitVarTemplateSpecializationDecl(const VarTemplateSpecializationDecl *D) {
-      dumpTemplateArgumentList(D->getTemplateArgs());
-      VisitVarDecl(D);
-    }
-
-    void VisitVarTemplatePartialSpecializationDecl(
-        const VarTemplatePartialSpecializationDecl *D) {
-      dumpTemplateParameters(D->getTemplateParameters());
-      VisitVarTemplateSpecializationDecl(D);
-    }
-
-    void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) {
-      if (D->hasDefaultArgument())
-        Visit(D->getDefaultArgument(), SourceRange(),
-              D->getDefaultArgStorage().getInheritedFrom(),
-              D->defaultArgumentWasInherited() ? "inherited from" : "previous");
-    }
-
-    void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D) {
-      if (D->hasDefaultArgument())
-        Visit(D->getDefaultArgument(), SourceRange(),
-              D->getDefaultArgStorage().getInheritedFrom(),
-              D->defaultArgumentWasInherited() ? "inherited from" : "previous");
-    }
-
-    void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D) {
-      dumpTemplateParameters(D->getTemplateParameters());
-      if (D->hasDefaultArgument())
-        dumpTemplateArgumentLoc(
-            D->getDefaultArgument(),
-            D->getDefaultArgStorage().getInheritedFrom(),
-            D->defaultArgumentWasInherited() ? "inherited from" : "previous");
-    }
-
-    void VisitUsingShadowDecl(const UsingShadowDecl *D) {
-      if (auto *TD = dyn_cast<TypeDecl>(D->getUnderlyingDecl()))
-        Visit(TD->getTypeForDecl());
-    }
-
-    void VisitFriendDecl(const FriendDecl *D) {
-      if (!D->getFriendType())
-        Visit(D->getFriendDecl());
-    }
-
-    void VisitObjCMethodDecl(const ObjCMethodDecl *D) {
-      if (D->isThisDeclarationADefinition())
-        dumpDeclContext(D);
-      else
-        for (const ParmVarDecl *Parameter : D->parameters())
-          Visit(Parameter);
-
-      if (D->hasBody())
-        Visit(D->getBody());
-    }
-
-    void VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
-      dumpObjCTypeParamList(D->getTypeParamList());
-    }
-
-    void VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
-      dumpObjCTypeParamList(D->getTypeParamListAsWritten());
-    }
-
-    void VisitObjCImplementationDecl(const ObjCImplementationDecl *D) {
-      for (const auto &I : D->inits())
-        Visit(I);
-    }
-
-    void VisitBlockDecl(const BlockDecl *D) {
-      for (const auto &I : D->parameters())
-        Visit(I);
-
-      for (const auto &I : D->captures())
-        Visit(I);
-      Visit(D->getBody());
-    }
-
-    void VisitDeclStmt(const DeclStmt *Node) {
-      for (const auto &D : Node->decls())
-        Visit(D);
-    }
-
-    void VisitAttributedStmt(const AttributedStmt *Node) {
-      for (const auto *A : Node->getAttrs())
-        Visit(A);
-    }
-
-    void VisitCXXCatchStmt(const CXXCatchStmt *Node) {
-      Visit(Node->getExceptionDecl());
-    }
-
-    void VisitCapturedStmt(const CapturedStmt *Node) {
-      Visit(Node->getCapturedDecl());
-    }
-
-    void VisitOMPExecutableDirective(const OMPExecutableDirective *Node) {
-      for (const auto *C : Node->clauses())
-        Visit(C);
-    }
-
-    void VisitInitListExpr(const InitListExpr *ILE) {
-      if (auto *Filler = ILE->getArrayFiller()) {
-        Visit(Filler, "array_filler");
-      }
-    }
-
-    void VisitBlockExpr(const BlockExpr *Node) { Visit(Node->getBlockDecl()); }
-
-    void VisitOpaqueValueExpr(const OpaqueValueExpr *Node) {
-      if (Expr *Source = Node->getSourceExpr())
-        Visit(Source);
-    }
-
-    void VisitGenericSelectionExpr(const GenericSelectionExpr *E) {
-      Visit(E->getControllingExpr());
-      Visit(E->getControllingExpr()->getType()); // FIXME: remove
-
-      for (const auto &Assoc : E->associations()) {
-        Visit(Assoc);
-      }
-    }
-
-    void VisitLambdaExpr(const LambdaExpr *Node) {
-      Visit(Node->getLambdaClass());
-    }
-
-    void VisitSizeOfPackExpr(const SizeOfPackExpr *Node) {
-      if (Node->isPartiallySubstituted())
-        for (const auto &A : Node->getPartialArguments())
-          Visit(A);
-    }
-
-    void VisitObjCAtCatchStmt(const ObjCAtCatchStmt *Node) {
-      if (const VarDecl *CatchParam = Node->getCatchParamDecl())
-        Visit(CatchParam);
-    }
-
-    void VisitExpressionTemplateArgument(const TemplateArgument &TA) {
-      Visit(TA.getAsExpr());
-    }
-    void VisitPackTemplateArgument(const TemplateArgument &TA) {
-      for (const auto &TArg : TA.pack_elements())
-        Visit(TArg);
-    }
-
-    // Implements Visit methods for Attrs.
-#include "clang/AST/AttrNodeTraverse.inc"
-  };
+  void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D);
+  void VisitClassTemplateDecl(const ClassTemplateDecl *D);
+  void VisitVarTemplateDecl(const VarTemplateDecl *D);
+};
 } // namespace
 
-void ASTDumper::dumpDeclContext(const DeclContext *DC) {
-  if (!DC)
-    return;
-
-  for (const auto *D : (Deserialize ? DC->decls() : DC->noload_decls()))
-    Visit(D);
-}
-
 void ASTDumper::dumpLookups(const DeclContext *DC, bool DumpDecls) {
   NodeDumper.AddChild([=] {
     OS << "StoredDeclsMap ";
@@ -608,7 +79,7 @@
 
     bool HasUndeserializedLookups = Primary->hasExternalVisibleStorage();
 
-    auto Range = Deserialize
+    auto Range = getDeserialize()
                      ? Primary->lookups()
                      : Primary->noload_lookups(/*PreserveInternalState=*/true);
     for (auto I = Range.begin(), E = Range.end(); I != E; ++I) {