mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-26 23:26:05 +00:00
[Clang] [NFC] Introduce DynamicRecursiveASTVisitor
(#110040)
See #105195 as well as the big comment in DynamicRecursiveASTVisitor.cpp for more context.
This commit is contained in:
parent
5f8b83e40c
commit
ff5551cdb0
276
clang/include/clang/AST/DynamicRecursiveASTVisitor.h
Normal file
276
clang/include/clang/AST/DynamicRecursiveASTVisitor.h
Normal file
@ -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 difference 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
|
@ -53,6 +53,7 @@ add_clang_library(clangAST
|
||||
DeclOpenMP.cpp
|
||||
DeclPrinter.cpp
|
||||
DeclTemplate.cpp
|
||||
DynamicRecursiveASTVisitor.cpp
|
||||
ParentMapContext.cpp
|
||||
Expr.cpp
|
||||
ExprClassification.cpp
|
||||
|
452
clang/lib/AST/DynamicRecursiveASTVisitor.cpp
Normal file
452
clang/lib/AST/DynamicRecursiveASTVisitor.cpp
Normal file
@ -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"
|
Loading…
x
Reference in New Issue
Block a user