[clang] ff5551c - [Clang] [NFC] Introduce `DynamicRecursiveASTVisitor` (#110040)

via cfe-commits cfe-commits at lists.llvm.org
Tue Nov 5 10:23:48 PST 2024


Author: Sirraide
Date: 2024-11-05T19:23:44+01:00
New Revision: ff5551cdb07f07e15900be3593c56c5760f8dd38

URL: https://github.com/llvm/llvm-project/commit/ff5551cdb07f07e15900be3593c56c5760f8dd38
DIFF: https://github.com/llvm/llvm-project/commit/ff5551cdb07f07e15900be3593c56c5760f8dd38.diff

LOG: [Clang] [NFC] Introduce `DynamicRecursiveASTVisitor` (#110040)

See #105195 as well as the big comment in DynamicRecursiveASTVisitor.cpp
for more context.

Added: 
    clang/include/clang/AST/DynamicRecursiveASTVisitor.h
    clang/lib/AST/DynamicRecursiveASTVisitor.cpp

Modified: 
    clang/lib/AST/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/AST/DynamicRecursiveASTVisitor.h b/clang/include/clang/AST/DynamicRecursiveASTVisitor.h
new file mode 100644
index 00000000000000..4382d209908292
--- /dev/null
+++ b/clang/include/clang/AST/DynamicRecursiveASTVisitor.h
@@ -0,0 +1,276 @@
+//===--- DynamicRecursiveASTVisitor.h - Virtual AST Visitor -----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file defines the DynamicRecursiveASTVisitor interface, which acts
+//  identically to RecursiveASTVisitor, except that it uses virtual dispatch
+//  instead of CRTP, which greatly improves compile times and binary size.
+//
+//  Prefer to use this over RecursiveASTVisitor whenever possible.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_AST_DYNAMIC_RECURSIVE_AST_VISITOR_H
+#define LLVM_CLANG_AST_DYNAMIC_RECURSIVE_AST_VISITOR_H
+
+#include "clang/AST/Attr.h"
+#include "clang/AST/ExprConcepts.h"
+#include "clang/AST/TypeLoc.h"
+
+namespace clang {
+class ASTContext;
+
+/// Recursive AST visitor that supports extension via dynamic dispatch.
+///
+/// Like RecursiveASTVisitor, this class allows for traversal of arbitrarily
+/// complex ASTs. The main 
diff erence is that this uses virtual functions
+/// instead of CRTP, which greatly improves compile times of Clang itself,
+/// as well as binary size.
+///
+/// Instead of functions (e.g. shouldVisitImplicitCode()), this class
+/// uses member variables (e.g. ShouldVisitImplicitCode) to control
+/// visitation behaviour.
+///
+/// However, there is no support for overriding some of the less commonly
+/// used features of the RAV, such as WalkUpFromX or attribute traversal
+/// (attributes can still be traversed, but you can't change what happens
+/// when we traverse one).
+///
+/// The following is a list of RAV features that are NOT customisable:
+///
+///   - Visiting attributes,
+///   - Overriding WalkUpFromX,
+///   - Overriding getStmtChildren().
+///
+/// Furthermore, post-order traversal is not supported at all.
+///
+/// Prefer to use this over RecursiveASTVisitor unless you absolutely
+/// need to use one of the features listed above (e.g. overriding
+/// WalkUpFromX or post-order traversal).
+///
+/// \see RecursiveASTVisitor.
+class DynamicRecursiveASTVisitor {
+public:
+  /// Whether this visitor should recurse into template instantiations.
+  bool ShouldVisitTemplateInstantiations = false;
+
+  /// Whether this visitor should recurse into the types of TypeLocs.
+  bool ShouldWalkTypesOfTypeLocs = true;
+
+  /// Whether this visitor should recurse into implicit code, e.g.
+  /// implicit constructors and destructors.
+  bool ShouldVisitImplicitCode = false;
+
+  /// Whether this visitor should recurse into lambda body.
+  bool ShouldVisitLambdaBody = true;
+
+protected:
+  DynamicRecursiveASTVisitor() = default;
+  DynamicRecursiveASTVisitor(DynamicRecursiveASTVisitor &&) = default;
+  DynamicRecursiveASTVisitor(const DynamicRecursiveASTVisitor &) = default;
+  DynamicRecursiveASTVisitor &
+  operator=(DynamicRecursiveASTVisitor &&) = default;
+  DynamicRecursiveASTVisitor &
+  operator=(const DynamicRecursiveASTVisitor &) = default;
+
+public:
+  virtual void anchor();
+  virtual ~DynamicRecursiveASTVisitor() = default;
+
+  /// Recursively visits an entire AST, starting from the TranslationUnitDecl.
+  /// \returns false if visitation was terminated early.
+  virtual bool TraverseAST(ASTContext &AST);
+
+  /// Recursively visit an attribute, by dispatching to
+  /// Traverse*Attr() based on the argument's dynamic type.
+  ///
+  /// \returns false if the visitation was terminated early, true
+  /// otherwise (including when the argument is a Null type location).
+  virtual bool TraverseAttr(Attr *At);
+
+  /// Recursively visit a constructor initializer.  This
+  /// automatically dispatches to another visitor for the initializer
+  /// expression, but not for the name of the initializer, so may
+  /// be overridden for clients that need access to the name.
+  ///
+  /// \returns false if the visitation was terminated early, true otherwise.
+  virtual bool TraverseConstructorInitializer(CXXCtorInitializer *Init);
+
+  /// Recursively visit a base specifier. This can be overridden by a
+  /// subclass.
+  ///
+  /// \returns false if the visitation was terminated early, true otherwise.
+  virtual bool TraverseCXXBaseSpecifier(const CXXBaseSpecifier &Base);
+
+  /// Recursively visit a declaration, by dispatching to
+  /// Traverse*Decl() based on the argument's dynamic type.
+  ///
+  /// \returns false if the visitation was terminated early, true
+  /// otherwise (including when the argument is NULL).
+  virtual bool TraverseDecl(Decl *D);
+
+  /// Recursively visit a name with its location information.
+  ///
+  /// \returns false if the visitation was terminated early, true otherwise.
+  virtual bool TraverseDeclarationNameInfo(DeclarationNameInfo NameInfo);
+
+  /// Recursively visit a lambda capture. \c Init is the expression that
+  /// will be used to initialize the capture.
+  ///
+  /// \returns false if the visitation was terminated early, true otherwise.
+  virtual bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C,
+                                     Expr *Init);
+
+  /// Recursively visit a C++ nested-name-specifier.
+  ///
+  /// \returns false if the visitation was terminated early, true otherwise.
+  virtual bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS);
+
+  /// Recursively visit a C++ nested-name-specifier with location
+  /// information.
+  ///
+  /// \returns false if the visitation was terminated early, true otherwise.
+  virtual bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS);
+
+  /// Recursively visit a statement or expression, by
+  /// dispatching to Traverse*() based on the argument's dynamic type.
+  ///
+  /// \returns false if the visitation was terminated early, true
+  /// otherwise (including when the argument is nullptr).
+  virtual bool TraverseStmt(Stmt *S);
+
+  /// Recursively visit a template argument and dispatch to the
+  /// appropriate method for the argument type.
+  ///
+  /// \returns false if the visitation was terminated early, true otherwise.
+  // FIXME: migrate callers to TemplateArgumentLoc instead.
+  virtual bool TraverseTemplateArgument(const TemplateArgument &Arg);
+
+  /// Recursively visit a template argument location and dispatch to the
+  /// appropriate method for the argument type.
+  ///
+  /// \returns false if the visitation was terminated early, true otherwise.
+  virtual bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc);
+
+  /// Recursively visit a set of template arguments.
+  ///
+  /// \returns false if the visitation was terminated early, true otherwise.
+  // FIXME: take a TemplateArgumentLoc* (or TemplateArgumentListInfo) instead.
+  // Not virtual for now because no-one overrides it.
+  bool TraverseTemplateArguments(ArrayRef<TemplateArgument> Args);
+
+  /// Recursively visit a template name and dispatch to the
+  /// appropriate method.
+  ///
+  /// \returns false if the visitation was terminated early, true otherwise.
+  virtual bool TraverseTemplateName(TemplateName Template);
+
+  /// Recursively visit a type, by dispatching to
+  /// Traverse*Type() based on the argument's getTypeClass() property.
+  ///
+  /// \returns false if the visitation was terminated early, true
+  /// otherwise (including when the argument is a Null type).
+  virtual bool TraverseType(QualType T);
+
+  /// Recursively visit a type with location, by dispatching to
+  /// Traverse*TypeLoc() based on the argument type's getTypeClass() property.
+  ///
+  /// \returns false if the visitation was terminated early, true
+  /// otherwise (including when the argument is a Null type location).
+  virtual bool TraverseTypeLoc(TypeLoc TL);
+
+  /// Recursively visit an Objective-C protocol reference with location
+  /// information.
+  ///
+  /// \returns false if the visitation was terminated early, true otherwise.
+  virtual bool TraverseObjCProtocolLoc(ObjCProtocolLoc ProtocolLoc);
+
+  /// Traverse a concept (requirement).
+  virtual bool TraverseTypeConstraint(const TypeConstraint *C);
+  virtual bool TraverseConceptRequirement(concepts::Requirement *R);
+  virtual bool TraverseConceptTypeRequirement(concepts::TypeRequirement *R);
+  virtual bool TraverseConceptExprRequirement(concepts::ExprRequirement *R);
+  virtual bool TraverseConceptNestedRequirement(concepts::NestedRequirement *R);
+  virtual bool TraverseConceptReference(ConceptReference *CR);
+  virtual bool VisitConceptReference(ConceptReference *CR) { return true; }
+
+  /// Visit a node.
+  virtual bool VisitAttr(Attr *A) { return true; }
+  virtual bool VisitDecl(Decl *D) { return true; }
+  virtual bool VisitStmt(Stmt *S) { return true; }
+  virtual bool VisitType(Type *T) { return true; }
+  virtual bool VisitTypeLoc(TypeLoc TL) { return true; }
+
+  /// Walk up from a node.
+  bool WalkUpFromDecl(Decl *D) { return VisitDecl(D); }
+  bool WalkUpFromStmt(Stmt *S) { return VisitStmt(S); }
+  bool WalkUpFromType(Type *T) { return VisitType(T); }
+  bool WalkUpFromTypeLoc(TypeLoc TL) { return VisitTypeLoc(TL); }
+
+  /// Invoked before visiting a statement or expression via data recursion.
+  ///
+  /// \returns false to skip visiting the node, true otherwise.
+  virtual bool dataTraverseStmtPre(Stmt *S) { return true; }
+
+  /// Invoked after visiting a statement or expression via data recursion.
+  /// This is not invoked if the previously invoked \c dataTraverseStmtPre
+  /// returned false.
+  ///
+  /// \returns false if the visitation was terminated early, true otherwise.
+  virtual bool dataTraverseStmtPost(Stmt *S) { return true; }
+  virtual bool dataTraverseNode(Stmt *S);
+
+#define DEF_TRAVERSE_TMPL_INST(kind)                                           \
+  virtual bool TraverseTemplateInstantiations(kind##TemplateDecl *D);
+  DEF_TRAVERSE_TMPL_INST(Class)
+  DEF_TRAVERSE_TMPL_INST(Var)
+  DEF_TRAVERSE_TMPL_INST(Function)
+#undef DEF_TRAVERSE_TMPL_INST
+
+  // Decls.
+#define ABSTRACT_DECL(DECL)
+#define DECL(CLASS, BASE) virtual bool Traverse##CLASS##Decl(CLASS##Decl *D);
+#include "clang/AST/DeclNodes.inc"
+
+#define DECL(CLASS, BASE)                                                      \
+  bool WalkUpFrom##CLASS##Decl(CLASS##Decl *D);                                \
+  virtual bool Visit##CLASS##Decl(CLASS##Decl *D) { return true; }
+#include "clang/AST/DeclNodes.inc"
+
+  // Stmts.
+#define ABSTRACT_STMT(STMT)
+#define STMT(CLASS, PARENT) virtual bool Traverse##CLASS(CLASS *S);
+#include "clang/AST/StmtNodes.inc"
+
+#define STMT(CLASS, PARENT)                                                    \
+  bool WalkUpFrom##CLASS(CLASS *S);                                            \
+  virtual bool Visit##CLASS(CLASS *S) { return true; }
+#include "clang/AST/StmtNodes.inc"
+
+  // Types.
+#define ABSTRACT_TYPE(CLASS, BASE)
+#define TYPE(CLASS, BASE) virtual bool Traverse##CLASS##Type(CLASS##Type *T);
+#include "clang/AST/TypeNodes.inc"
+
+#define TYPE(CLASS, BASE)                                                      \
+  bool WalkUpFrom##CLASS##Type(CLASS##Type *T);                                \
+  virtual bool Visit##CLASS##Type(CLASS##Type *T) { return true; }
+#include "clang/AST/TypeNodes.inc"
+
+  // TypeLocs.
+#define ABSTRACT_TYPELOC(CLASS, BASE)
+#define TYPELOC(CLASS, BASE)                                                   \
+  virtual bool Traverse##CLASS##TypeLoc(CLASS##TypeLoc TL);
+#include "clang/AST/TypeLocNodes.def"
+
+#define TYPELOC(CLASS, BASE)                                                   \
+  bool WalkUpFrom##CLASS##TypeLoc(CLASS##TypeLoc TL);                          \
+  virtual bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TL) { return true; }
+#include "clang/AST/TypeLocNodes.def"
+};
+} // namespace clang
+
+#endif // LLVM_CLANG_AST_DYNAMIC_RECURSIVE_AST_VISITOR_H

diff  --git a/clang/lib/AST/CMakeLists.txt b/clang/lib/AST/CMakeLists.txt
index 038856248c1604..52c6a45de9a26c 100644
--- a/clang/lib/AST/CMakeLists.txt
+++ b/clang/lib/AST/CMakeLists.txt
@@ -53,6 +53,7 @@ add_clang_library(clangAST
   DeclOpenMP.cpp
   DeclPrinter.cpp
   DeclTemplate.cpp
+  DynamicRecursiveASTVisitor.cpp
   ParentMapContext.cpp
   Expr.cpp
   ExprClassification.cpp

diff  --git a/clang/lib/AST/DynamicRecursiveASTVisitor.cpp b/clang/lib/AST/DynamicRecursiveASTVisitor.cpp
new file mode 100644
index 00000000000000..8cfabd9f3e93fe
--- /dev/null
+++ b/clang/lib/AST/DynamicRecursiveASTVisitor.cpp
@@ -0,0 +1,452 @@
+//=== DynamicRecursiveASTVisitor.cpp - Dynamic AST Visitor Implementation -===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements DynamicRecursiveASTVisitor in terms of the CRTP-based
+// RecursiveASTVisitor.
+//
+//===----------------------------------------------------------------------===//
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+
+using namespace clang;
+
+// The implementation of DRAV deserves some explanation:
+//
+// We want to implement DynamicRecursiveASTVisitor without having to inherit or
+// reference RecursiveASTVisitor in any way in the header: if we instantiate
+// RAV in the header, then every user of (or rather every file that uses) DRAV
+// still has to instantiate a RAV, which gets us nowhere. Moreover, even just
+// including RecursiveASTVisitor.h would probably cause some amount of slowdown
+// because we'd have to parse a huge template. For these reasons, the fact that
+// DRAV is implemented using a RAV is solely an implementation detail.
+//
+// As for the implementation itself, DRAV by default acts exactly like a RAV
+// that overrides none of RAV's functions. There are two parts to this:
+//
+//   1. Any function in DRAV has to act like the corresponding function in RAV,
+//      unless overridden by a derived class, of course.
+//
+//   2. Any call to a function by the RAV implementation that DRAV allows to be
+//      overridden must be transformed to a virtual call on the user-provided
+//      DRAV object: if some function in RAV calls e.g. TraverseCallExpr()
+//      during traversal, then the derived class's TraverseCallExpr() must be
+//      called (provided it overrides TraverseCallExpr()).
+//
+// The 'Impl' class is a helper that connects the two implementations; it is
+// a wrapper around a reference to a DRAV that is itself a RecursiveASTVisitor.
+// It overrides every function in RAV *that is virtual in DRAV* to perform a
+// virtual call on its DRAV reference. This accomplishes point 2 above.
+//
+// Point 1 is accomplished by, first, having the base class implementation of
+// each of the virtual functions construct an Impl object (which is actually
+// just a no-op), passing in itself so that any virtual calls use the right
+// vtable. Secondly, it then calls RAV's implementation of that same function
+// *on Impl* (using a qualified call so that we actually call into the RAV
+// implementation instead of Impl's version of that same function); this way,
+// we both execute RAV's implementation for this function only and ensure that
+// calls to subsequent functions call into Impl via CRTP (and Impl then calls
+// back into DRAV and so on).
+//
+// While this ends up constructing a lot of Impl instances (almost one per
+// function call), this doesn't really matter since Impl just holds a single
+// pointer, and everything in this file should get inlined into all the DRAV
+// functions here anyway.
+//
+//===----------------------------------------------------------------------===//
+//
+// The following illustrates how a call to an (overridden) function is actually
+// resolved: given some class 'Derived' that derives from DRAV and overrides
+// TraverseStmt(), if we are traversing some AST, and TraverseStmt() is called
+// by the RAV implementation, the following happens:
+//
+//   1. Impl::TraverseStmt() overrides RAV::TraverseStmt() via CRTP, so the
+//      former is called.
+//
+//   2. Impl::TraverseStmt() performs a virtual call to the visitor (which is
+//      an instance to Derived), so Derived::TraverseStmt() is called.
+//
+//   End result: Derived::TraverseStmt() is executed.
+//
+// Suppose some other function, e.g. TraverseCallExpr(), which is NOT overridden
+// by Derived is called, we get:
+//
+//   1. Impl::TraverseCallExpr() overrides RAV::TraverseCallExpr() via CRTP,
+//      so the former is called.
+//
+//   2. Impl::TraverseCallExpr() performs a virtual call, but since Derived
+//      does not override that function, DRAV::TraverseCallExpr() is called.
+//
+//   3. DRAV::TraverseCallExpr() creates a new instance of Impl, passing in
+//      itself (this doesn't change that the pointer is an instance of Derived);
+//      it then calls RAV::TraverseCallExpr() on the Impl object, which actually
+//      ends up executing RAV's implementation because we used a qualified
+//      function call.
+//
+//   End result: RAV::TraverseCallExpr() is executed,
+namespace {
+struct Impl : RecursiveASTVisitor<Impl> {
+  DynamicRecursiveASTVisitor &Visitor;
+  Impl(DynamicRecursiveASTVisitor &Visitor) : Visitor(Visitor) {}
+
+  bool shouldVisitTemplateInstantiations() const {
+    return Visitor.ShouldVisitTemplateInstantiations;
+  }
+
+  bool shouldWalkTypesOfTypeLocs() const {
+    return Visitor.ShouldWalkTypesOfTypeLocs;
+  }
+
+  bool shouldVisitImplicitCode() const {
+    return Visitor.ShouldVisitImplicitCode;
+  }
+
+  bool shouldVisitLambdaBody() const { return Visitor.ShouldVisitLambdaBody; }
+
+  // Supporting post-order would be very hard because of quirks of the
+  // RAV implementation that only work with CRTP. It also is only used
+  // by less than 5 visitors in the entire code base.
+  bool shouldTraversePostOrder() const { return false; }
+
+  bool TraverseAST(ASTContext &AST) { return Visitor.TraverseAST(AST); }
+  bool TraverseAttr(Attr *At) { return Visitor.TraverseAttr(At); }
+  bool TraverseDecl(Decl *D) { return Visitor.TraverseDecl(D); }
+  bool TraverseType(QualType T) { return Visitor.TraverseType(T); }
+  bool TraverseTypeLoc(TypeLoc TL) { return Visitor.TraverseTypeLoc(TL); }
+  bool TraverseStmt(Stmt *S) { return Visitor.TraverseStmt(S); }
+
+  bool TraverseConstructorInitializer(CXXCtorInitializer *Init) {
+    return Visitor.TraverseConstructorInitializer(Init);
+  }
+
+  bool TraverseTemplateArgument(const TemplateArgument &Arg) {
+    return Visitor.TraverseTemplateArgument(Arg);
+  }
+
+  bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc) {
+    return Visitor.TraverseTemplateArgumentLoc(ArgLoc);
+  }
+
+  bool TraverseTemplateName(TemplateName Template) {
+    return Visitor.TraverseTemplateName(Template);
+  }
+
+  bool TraverseObjCProtocolLoc(ObjCProtocolLoc ProtocolLoc) {
+    return Visitor.TraverseObjCProtocolLoc(ProtocolLoc);
+  }
+
+  bool TraverseTypeConstraint(const TypeConstraint *C) {
+    return Visitor.TraverseTypeConstraint(C);
+  }
+  bool TraverseConceptRequirement(concepts::Requirement *R) {
+    return Visitor.TraverseConceptRequirement(R);
+  }
+  bool TraverseConceptTypeRequirement(concepts::TypeRequirement *R) {
+    return Visitor.TraverseConceptTypeRequirement(R);
+  }
+  bool TraverseConceptExprRequirement(concepts::ExprRequirement *R) {
+    return Visitor.TraverseConceptExprRequirement(R);
+  }
+  bool TraverseConceptNestedRequirement(concepts::NestedRequirement *R) {
+    return Visitor.TraverseConceptNestedRequirement(R);
+  }
+
+  bool TraverseConceptReference(ConceptReference *CR) {
+    return Visitor.TraverseConceptReference(CR);
+  }
+
+  bool TraverseCXXBaseSpecifier(const CXXBaseSpecifier &Base) {
+    return Visitor.TraverseCXXBaseSpecifier(Base);
+  }
+
+  bool TraverseDeclarationNameInfo(DeclarationNameInfo NameInfo) {
+    return Visitor.TraverseDeclarationNameInfo(NameInfo);
+  }
+
+  bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C,
+                             Expr *Init) {
+    return Visitor.TraverseLambdaCapture(LE, C, Init);
+  }
+
+  bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS) {
+    return Visitor.TraverseNestedNameSpecifier(NNS);
+  }
+
+  bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
+    return Visitor.TraverseNestedNameSpecifierLoc(NNS);
+  }
+
+  bool VisitConceptReference(ConceptReference *CR) {
+    return Visitor.VisitConceptReference(CR);
+  }
+
+  bool dataTraverseStmtPre(Stmt *S) { return Visitor.dataTraverseStmtPre(S); }
+  bool dataTraverseStmtPost(Stmt *S) { return Visitor.dataTraverseStmtPost(S); }
+
+  // TraverseStmt() always passes in a queue, so we have no choice but to
+  // accept it as a parameter here.
+  bool dataTraverseNode(Stmt *S, DataRecursionQueue * = nullptr) {
+    // But since don't support postorder traversal, we don't need it, so
+    // simply discard it here. This way, derived classes don't need to worry
+    // about including it as a parameter that they never use.
+    return Visitor.dataTraverseNode(S);
+  }
+
+  /// Visit a node.
+  bool VisitAttr(Attr *A) { return Visitor.VisitAttr(A); }
+  bool VisitDecl(Decl *D) { return Visitor.VisitDecl(D); }
+  bool VisitStmt(Stmt *S) { return Visitor.VisitStmt(S); }
+  bool VisitType(Type *T) { return Visitor.VisitType(T); }
+  bool VisitTypeLoc(TypeLoc TL) { return Visitor.VisitTypeLoc(TL); }
+
+#define DEF_TRAVERSE_TMPL_INST(kind)                                           \
+  bool TraverseTemplateInstantiations(kind##TemplateDecl *D) {                 \
+    return Visitor.TraverseTemplateInstantiations(D);                          \
+  }
+  DEF_TRAVERSE_TMPL_INST(Class)
+  DEF_TRAVERSE_TMPL_INST(Var)
+  DEF_TRAVERSE_TMPL_INST(Function)
+#undef DEF_TRAVERSE_TMPL_INST
+
+  // Decls.
+#define ABSTRACT_DECL(DECL)
+#define DECL(CLASS, BASE)                                                      \
+  bool Traverse##CLASS##Decl(CLASS##Decl *D) {                                 \
+    return Visitor.Traverse##CLASS##Decl(D);                                   \
+  }
+#include "clang/AST/DeclNodes.inc"
+
+#define DECL(CLASS, BASE)                                                      \
+  bool Visit##CLASS##Decl(CLASS##Decl *D) {                                    \
+    return Visitor.Visit##CLASS##Decl(D);                                      \
+  }
+#include "clang/AST/DeclNodes.inc"
+
+  // Stmts.
+#define ABSTRACT_STMT(STMT)
+#define STMT(CLASS, PARENT)                                                    \
+  bool Traverse##CLASS(CLASS *S) { return Visitor.Traverse##CLASS(S); }
+#include "clang/AST/StmtNodes.inc"
+
+#define STMT(CLASS, PARENT)                                                    \
+  bool Visit##CLASS(CLASS *S) { return Visitor.Visit##CLASS(S); }
+#include "clang/AST/StmtNodes.inc"
+
+  // Types.
+#define ABSTRACT_TYPE(CLASS, BASE)
+#define TYPE(CLASS, BASE)                                                      \
+  bool Traverse##CLASS##Type(CLASS##Type *T) {                                 \
+    return Visitor.Traverse##CLASS##Type(T);                                   \
+  }
+#include "clang/AST/TypeNodes.inc"
+
+#define TYPE(CLASS, BASE)                                                      \
+  bool Visit##CLASS##Type(CLASS##Type *T) {                                    \
+    return Visitor.Visit##CLASS##Type(T);                                      \
+  }
+#include "clang/AST/TypeNodes.inc"
+
+  // TypeLocs.
+#define ABSTRACT_TYPELOC(CLASS, BASE)
+#define TYPELOC(CLASS, BASE)                                                   \
+  bool Traverse##CLASS##TypeLoc(CLASS##TypeLoc TL) {                           \
+    return Visitor.Traverse##CLASS##TypeLoc(TL);                               \
+  }
+#include "clang/AST/TypeLocNodes.def"
+
+#define TYPELOC(CLASS, BASE)                                                   \
+  bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TL) {                              \
+    return Visitor.Visit##CLASS##TypeLoc(TL);                                  \
+  }
+#include "clang/AST/TypeLocNodes.def"
+};
+} // namespace
+
+void DynamicRecursiveASTVisitor::anchor() {}
+
+bool DynamicRecursiveASTVisitor::TraverseAST(ASTContext &AST) {
+  return Impl(*this).RecursiveASTVisitor<Impl>::TraverseAST(AST);
+}
+
+bool DynamicRecursiveASTVisitor::TraverseAttr(Attr *At) {
+  return Impl(*this).RecursiveASTVisitor<Impl>::TraverseAttr(At);
+}
+
+bool DynamicRecursiveASTVisitor::TraverseConstructorInitializer(
+    CXXCtorInitializer *Init) {
+  return Impl(*this).RecursiveASTVisitor<Impl>::TraverseConstructorInitializer(
+      Init);
+}
+
+bool DynamicRecursiveASTVisitor::TraverseDecl(Decl *D) {
+  return Impl(*this).RecursiveASTVisitor<Impl>::TraverseDecl(D);
+}
+
+bool DynamicRecursiveASTVisitor::TraverseLambdaCapture(LambdaExpr *LE,
+                                                       const LambdaCapture *C,
+                                                       Expr *Init) {
+  return Impl(*this).RecursiveASTVisitor<Impl>::TraverseLambdaCapture(LE, C,
+                                                                      Init);
+}
+
+bool DynamicRecursiveASTVisitor::TraverseStmt(Stmt *S) {
+  return Impl(*this).RecursiveASTVisitor<Impl>::TraverseStmt(S);
+}
+
+bool DynamicRecursiveASTVisitor::TraverseTemplateArgument(
+    const TemplateArgument &Arg) {
+  return Impl(*this).RecursiveASTVisitor<Impl>::TraverseTemplateArgument(Arg);
+}
+
+bool DynamicRecursiveASTVisitor::TraverseTemplateArguments(
+    ArrayRef<TemplateArgument> Args) {
+  return Impl(*this).RecursiveASTVisitor<Impl>::TraverseTemplateArguments(Args);
+}
+
+bool DynamicRecursiveASTVisitor::TraverseTemplateArgumentLoc(
+    const TemplateArgumentLoc &ArgLoc) {
+  return Impl(*this).RecursiveASTVisitor<Impl>::TraverseTemplateArgumentLoc(
+      ArgLoc);
+}
+
+bool DynamicRecursiveASTVisitor::TraverseTemplateName(TemplateName Template) {
+  return Impl(*this).RecursiveASTVisitor<Impl>::TraverseTemplateName(Template);
+}
+
+bool DynamicRecursiveASTVisitor::TraverseType(QualType T) {
+  return Impl(*this).RecursiveASTVisitor<Impl>::TraverseType(T);
+}
+
+bool DynamicRecursiveASTVisitor::TraverseTypeLoc(TypeLoc TL) {
+  return Impl(*this).RecursiveASTVisitor<Impl>::TraverseTypeLoc(TL);
+}
+
+bool DynamicRecursiveASTVisitor::TraverseTypeConstraint(
+    const TypeConstraint *C) {
+  return Impl(*this).RecursiveASTVisitor<Impl>::TraverseTypeConstraint(C);
+}
+bool DynamicRecursiveASTVisitor::TraverseObjCProtocolLoc(
+    ObjCProtocolLoc ProtocolLoc) {
+  return Impl(*this).RecursiveASTVisitor<Impl>::TraverseObjCProtocolLoc(
+      ProtocolLoc);
+}
+
+bool DynamicRecursiveASTVisitor::TraverseConceptRequirement(
+    concepts::Requirement *R) {
+  return Impl(*this).RecursiveASTVisitor<Impl>::TraverseConceptRequirement(R);
+}
+bool DynamicRecursiveASTVisitor::TraverseConceptTypeRequirement(
+    concepts::TypeRequirement *R) {
+  return Impl(*this).RecursiveASTVisitor<Impl>::TraverseConceptTypeRequirement(
+      R);
+}
+bool DynamicRecursiveASTVisitor::TraverseConceptExprRequirement(
+    concepts::ExprRequirement *R) {
+  return Impl(*this).RecursiveASTVisitor<Impl>::TraverseConceptExprRequirement(
+      R);
+}
+bool DynamicRecursiveASTVisitor::TraverseConceptNestedRequirement(
+    concepts::NestedRequirement *R) {
+  return Impl(*this)
+      .RecursiveASTVisitor<Impl>::TraverseConceptNestedRequirement(R);
+}
+
+bool DynamicRecursiveASTVisitor::TraverseConceptReference(
+    ConceptReference *CR) {
+  return Impl(*this).RecursiveASTVisitor<Impl>::TraverseConceptReference(CR);
+}
+
+bool DynamicRecursiveASTVisitor::TraverseCXXBaseSpecifier(
+    const CXXBaseSpecifier &Base) {
+  return Impl(*this).RecursiveASTVisitor<Impl>::TraverseCXXBaseSpecifier(Base);
+}
+
+bool DynamicRecursiveASTVisitor::TraverseDeclarationNameInfo(
+    DeclarationNameInfo NameInfo) {
+  return Impl(*this).RecursiveASTVisitor<Impl>::TraverseDeclarationNameInfo(
+      NameInfo);
+}
+
+bool DynamicRecursiveASTVisitor::TraverseNestedNameSpecifier(
+    NestedNameSpecifier *NNS) {
+  return Impl(*this).RecursiveASTVisitor<Impl>::TraverseNestedNameSpecifier(
+      NNS);
+}
+
+bool DynamicRecursiveASTVisitor::TraverseNestedNameSpecifierLoc(
+    NestedNameSpecifierLoc NNS) {
+  return Impl(*this).RecursiveASTVisitor<Impl>::TraverseNestedNameSpecifierLoc(
+      NNS);
+}
+
+bool DynamicRecursiveASTVisitor::dataTraverseNode(Stmt *S) {
+  return Impl(*this).RecursiveASTVisitor<Impl>::dataTraverseNode(S, nullptr);
+}
+
+#define DEF_TRAVERSE_TMPL_INST(kind)                                           \
+  bool DynamicRecursiveASTVisitor::TraverseTemplateInstantiations(             \
+      kind##TemplateDecl *D) {                                                 \
+    return Impl(*this)                                                         \
+        .RecursiveASTVisitor<Impl>::TraverseTemplateInstantiations(D);         \
+  }
+DEF_TRAVERSE_TMPL_INST(Class)
+DEF_TRAVERSE_TMPL_INST(Var)
+DEF_TRAVERSE_TMPL_INST(Function)
+#undef DEF_TRAVERSE_TMPL_INST
+
+// Declare Traverse*() for and friends all concrete Decl classes.
+#define ABSTRACT_DECL(DECL)
+#define DECL(CLASS, BASE)                                                      \
+  bool DynamicRecursiveASTVisitor::Traverse##CLASS##Decl(CLASS##Decl *D) {     \
+    return Impl(*this).RecursiveASTVisitor<Impl>::Traverse##CLASS##Decl(D);    \
+  }                                                                            \
+  bool DynamicRecursiveASTVisitor::WalkUpFrom##CLASS##Decl(CLASS##Decl *D) {   \
+    return Impl(*this).RecursiveASTVisitor<Impl>::WalkUpFrom##CLASS##Decl(D);  \
+  }
+#include "clang/AST/DeclNodes.inc"
+
+// Declare Traverse*() and friends for all concrete Stmt classes.
+#define ABSTRACT_STMT(STMT)
+#define STMT(CLASS, PARENT)                                                    \
+  bool DynamicRecursiveASTVisitor::Traverse##CLASS(CLASS *S) {                 \
+    return Impl(*this).RecursiveASTVisitor<Impl>::Traverse##CLASS(S);          \
+  }
+#include "clang/AST/StmtNodes.inc"
+
+#define STMT(CLASS, PARENT)                                                    \
+  bool DynamicRecursiveASTVisitor::WalkUpFrom##CLASS(CLASS *S) {               \
+    return Impl(*this).RecursiveASTVisitor<Impl>::WalkUpFrom##CLASS(S);        \
+  }
+#include "clang/AST/StmtNodes.inc"
+
+// Declare Traverse*() and friends for all concrete Typeclasses.
+#define ABSTRACT_TYPE(CLASS, BASE)
+#define TYPE(CLASS, BASE)                                                      \
+  bool DynamicRecursiveASTVisitor::Traverse##CLASS##Type(CLASS##Type *T) {     \
+    return Impl(*this).RecursiveASTVisitor<Impl>::Traverse##CLASS##Type(T);    \
+  }                                                                            \
+  bool DynamicRecursiveASTVisitor::WalkUpFrom##CLASS##Type(CLASS##Type *T) {   \
+    return Impl(*this).RecursiveASTVisitor<Impl>::WalkUpFrom##CLASS##Type(T);  \
+  }
+#include "clang/AST/TypeNodes.inc"
+
+#define ABSTRACT_TYPELOC(CLASS, BASE)
+#define TYPELOC(CLASS, BASE)                                                   \
+  bool DynamicRecursiveASTVisitor::Traverse##CLASS##TypeLoc(                   \
+      CLASS##TypeLoc TL) {                                                     \
+    return Impl(*this).RecursiveASTVisitor<Impl>::Traverse##CLASS##TypeLoc(    \
+        TL);                                                                   \
+  }
+#include "clang/AST/TypeLocNodes.def"
+
+#define TYPELOC(CLASS, BASE)                                                   \
+  bool DynamicRecursiveASTVisitor::WalkUpFrom##CLASS##TypeLoc(                 \
+      CLASS##TypeLoc TL) {                                                     \
+    return Impl(*this).RecursiveASTVisitor<Impl>::WalkUpFrom##CLASS##TypeLoc(  \
+        TL);                                                                   \
+  }
+#include "clang/AST/TypeLocNodes.def"


        


More information about the cfe-commits mailing list