Skip to content

Commit a031dd9

Browse files
committed
[Clang] [AST] Introduce DynamicRecursiveASTVisitor
1 parent 8588c6e commit a031dd9

File tree

3 files changed

+721
-0
lines changed

3 files changed

+721
-0
lines changed
Lines changed: 268 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,268 @@
1+
//===--- DynamicRecursiveASTVisitor.h - Virtual AST Visitor -----*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file defines the DynamicRecursiveASTVisitor interface, which acts
10+
// identically to RecursiveASTVisitor, except that it uses virtual dispatch
11+
// instead of CRTP, which greatly improves compile times and binary size.
12+
//
13+
// However, it also comes with limitations in that some of the more seldom
14+
// utilised features of RecursiveASTVisitor are not supported.
15+
//
16+
// Prefer to use this over RecursiveASTVisitor whenever possible.
17+
//
18+
//===----------------------------------------------------------------------===//
19+
#ifndef LLVM_CLANG_AST_DYNAMIC_RECURSIVE_AST_VISITOR_H
20+
#define LLVM_CLANG_AST_DYNAMIC_RECURSIVE_AST_VISITOR_H
21+
22+
#include "clang/AST/Attr.h"
23+
#include "clang/AST/ExprConcepts.h"
24+
#include "clang/AST/TypeLoc.h"
25+
26+
namespace clang {
27+
class ASTContext;
28+
29+
/// Recursive AST visitor that supports extension via dynamic dispatch.
30+
///
31+
/// This only supports some of the more common visitation operations; in
32+
/// particular, it does not support overriding WalkUpFromX or post-order
33+
/// traversal.
34+
///
35+
/// Instead of functions (e.g. shouldVisitImplicitCode()), this class
36+
/// uses member variables (e.g. ShouldVisitImplicitCode) to control
37+
/// visitation behaviour.
38+
///
39+
/// RAV features that are NOT supported:
40+
///
41+
/// - Visiting attributes,
42+
/// - Post-order traversal,
43+
/// - Overriding WalkUpFromX,
44+
/// - Overriding getStmtChildren().
45+
///
46+
/// \see RecursiveASTVisitor.
47+
class DynamicRecursiveASTVisitor {
48+
public:
49+
/// Whether this visitor should recurse into template instantiations.
50+
bool ShouldVisitTemplateInstantiations = false;
51+
52+
/// Whether this visitor should recurse into the types of TypeLocs.
53+
bool ShouldWalkTypesOfTypeLocs = true;
54+
55+
/// Whether this visitor should recurse into implicit code, e.g.
56+
/// implicit constructors and destructors.
57+
bool ShouldVisitImplicitCode = false;
58+
59+
/// Whether this visitor should recurse into lambda body.
60+
bool ShouldVisitLambdaBody = true;
61+
62+
protected:
63+
DynamicRecursiveASTVisitor() = default;
64+
DynamicRecursiveASTVisitor(DynamicRecursiveASTVisitor &&) = default;
65+
DynamicRecursiveASTVisitor(const DynamicRecursiveASTVisitor &) = default;
66+
DynamicRecursiveASTVisitor &
67+
operator=(DynamicRecursiveASTVisitor &&) = default;
68+
DynamicRecursiveASTVisitor &
69+
operator=(const DynamicRecursiveASTVisitor &) = default;
70+
71+
public:
72+
virtual void anchor();
73+
virtual ~DynamicRecursiveASTVisitor() = default;
74+
75+
/// Recursively visits an entire AST, starting from the TranslationUnitDecl.
76+
/// \returns false if visitation was terminated early.
77+
virtual bool TraverseAST(ASTContext &AST);
78+
79+
/// Recursively visit an attribute, by dispatching to
80+
/// Traverse*Attr() based on the argument's dynamic type.
81+
///
82+
/// \returns false if the visitation was terminated early, true
83+
/// otherwise (including when the argument is a Null type location).
84+
virtual bool TraverseAttr(Attr *At);
85+
86+
/// Recursively visit a constructor initializer. This
87+
/// automatically dispatches to another visitor for the initializer
88+
/// expression, but not for the name of the initializer, so may
89+
/// be overridden for clients that need access to the name.
90+
///
91+
/// \returns false if the visitation was terminated early, true otherwise.
92+
virtual bool TraverseConstructorInitializer(CXXCtorInitializer *Init);
93+
94+
/// Recursively visit a base specifier. This can be overridden by a
95+
/// subclass.
96+
///
97+
/// \returns false if the visitation was terminated early, true otherwise.
98+
virtual bool TraverseCXXBaseSpecifier(const CXXBaseSpecifier &Base);
99+
100+
/// Recursively visit a declaration, by dispatching to
101+
/// Traverse*Decl() based on the argument's dynamic type.
102+
///
103+
/// \returns false if the visitation was terminated early, true
104+
/// otherwise (including when the argument is NULL).
105+
virtual bool TraverseDecl(Decl *D);
106+
107+
/// Recursively visit a name with its location information.
108+
///
109+
/// \returns false if the visitation was terminated early, true otherwise.
110+
virtual bool TraverseDeclarationNameInfo(DeclarationNameInfo NameInfo);
111+
112+
/// Recursively visit a lambda capture. \c Init is the expression that
113+
/// will be used to initialize the capture.
114+
///
115+
/// \returns false if the visitation was terminated early, true otherwise.
116+
virtual bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C,
117+
Expr *Init);
118+
119+
/// Recursively visit a C++ nested-name-specifier.
120+
///
121+
/// \returns false if the visitation was terminated early, true otherwise.
122+
virtual bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS);
123+
124+
/// Recursively visit a C++ nested-name-specifier with location
125+
/// information.
126+
///
127+
/// \returns false if the visitation was terminated early, true otherwise.
128+
virtual bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS);
129+
130+
/// Recursively visit a statement or expression, by
131+
/// dispatching to Traverse*() based on the argument's dynamic type.
132+
///
133+
/// \returns false if the visitation was terminated early, true
134+
/// otherwise (including when the argument is nullptr).
135+
virtual bool TraverseStmt(Stmt *S);
136+
137+
/// Recursively visit a template argument and dispatch to the
138+
/// appropriate method for the argument type.
139+
///
140+
/// \returns false if the visitation was terminated early, true otherwise.
141+
// FIXME: migrate callers to TemplateArgumentLoc instead.
142+
virtual bool TraverseTemplateArgument(const TemplateArgument &Arg);
143+
144+
/// Recursively visit a template argument location and dispatch to the
145+
/// appropriate method for the argument type.
146+
///
147+
/// \returns false if the visitation was terminated early, true otherwise.
148+
virtual bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc);
149+
150+
/// Recursively visit a set of template arguments.
151+
///
152+
/// \returns false if the visitation was terminated early, true otherwise.
153+
// FIXME: take a TemplateArgumentLoc* (or TemplateArgumentListInfo) instead.
154+
// Not virtual for now because no-one overrides it.
155+
bool TraverseTemplateArguments(ArrayRef<TemplateArgument> Args);
156+
157+
/// Recursively visit a template name and dispatch to the
158+
/// appropriate method.
159+
///
160+
/// \returns false if the visitation was terminated early, true otherwise.
161+
virtual bool TraverseTemplateName(TemplateName Template);
162+
163+
/// Recursively visit a type, by dispatching to
164+
/// Traverse*Type() based on the argument's getTypeClass() property.
165+
///
166+
/// \returns false if the visitation was terminated early, true
167+
/// otherwise (including when the argument is a Null type).
168+
virtual bool TraverseType(QualType T);
169+
170+
/// Recursively visit a type with location, by dispatching to
171+
/// Traverse*TypeLoc() based on the argument type's getTypeClass() property.
172+
///
173+
/// \returns false if the visitation was terminated early, true
174+
/// otherwise (including when the argument is a Null type location).
175+
virtual bool TraverseTypeLoc(TypeLoc TL);
176+
177+
/// Recursively visit an Objective-C protocol reference with location
178+
/// information.
179+
///
180+
/// \returns false if the visitation was terminated early, true otherwise.
181+
virtual bool TraverseObjCProtocolLoc(ObjCProtocolLoc ProtocolLoc);
182+
183+
/// Traverse a concept (requirement).
184+
virtual bool TraverseTypeConstraint(const TypeConstraint *C);
185+
virtual bool TraverseConceptRequirement(concepts::Requirement *R);
186+
virtual bool TraverseConceptTypeRequirement(concepts::TypeRequirement *R);
187+
virtual bool TraverseConceptExprRequirement(concepts::ExprRequirement *R);
188+
virtual bool TraverseConceptNestedRequirement(concepts::NestedRequirement *R);
189+
virtual bool TraverseConceptReference(ConceptReference *CR);
190+
virtual bool VisitConceptReference(ConceptReference *CR) { return true; }
191+
192+
/// Visit a node.
193+
virtual bool VisitAttr(Attr *A) { return true; }
194+
virtual bool VisitDecl(Decl *D) { return true; }
195+
virtual bool VisitStmt(Stmt *S) { return true; }
196+
virtual bool VisitType(Type *T) { return true; }
197+
virtual bool VisitTypeLoc(TypeLoc TL) { return true; }
198+
199+
/// Walk up from a node.
200+
bool WalkUpFromDecl(Decl *D) { return VisitDecl(D); }
201+
bool WalkUpFromStmt(Stmt *S) { return VisitStmt(S); }
202+
bool WalkUpFromType(Type *T) { return VisitType(T); }
203+
bool WalkUpFromTypeLoc(TypeLoc TL) { return VisitTypeLoc(TL); }
204+
205+
/// Invoked before visiting a statement or expression via data recursion.
206+
///
207+
/// \returns false to skip visiting the node, true otherwise.
208+
virtual bool dataTraverseStmtPre(Stmt *S) { return true; }
209+
210+
/// Invoked after visiting a statement or expression via data recursion.
211+
/// This is not invoked if the previously invoked \c dataTraverseStmtPre
212+
/// returned false.
213+
///
214+
/// \returns false if the visitation was terminated early, true otherwise.
215+
virtual bool dataTraverseStmtPost(Stmt *S) { return true; }
216+
virtual bool dataTraverseNode(Stmt *S);
217+
218+
#define DEF_TRAVERSE_TMPL_INST(kind) \
219+
virtual bool TraverseTemplateInstantiations(kind##TemplateDecl *D);
220+
DEF_TRAVERSE_TMPL_INST(Class)
221+
DEF_TRAVERSE_TMPL_INST(Var)
222+
DEF_TRAVERSE_TMPL_INST(Function)
223+
#undef DEF_TRAVERSE_TMPL_INST
224+
225+
// Decls.
226+
#define ABSTRACT_DECL(DECL)
227+
#define DECL(CLASS, BASE) virtual bool Traverse##CLASS##Decl(CLASS##Decl *D);
228+
#include "clang/AST/DeclNodes.inc"
229+
230+
#define DECL(CLASS, BASE) \
231+
bool WalkUpFrom##CLASS##Decl(CLASS##Decl *D); \
232+
virtual bool Visit##CLASS##Decl(CLASS##Decl *D) { return true; }
233+
#include "clang/AST/DeclNodes.inc"
234+
235+
// Stmts.
236+
#define ABSTRACT_STMT(STMT)
237+
#define STMT(CLASS, PARENT) virtual bool Traverse##CLASS(CLASS *S);
238+
#include "clang/AST/StmtNodes.inc"
239+
240+
#define STMT(CLASS, PARENT) \
241+
bool WalkUpFrom##CLASS(CLASS *S); \
242+
virtual bool Visit##CLASS(CLASS *S) { return true; }
243+
#include "clang/AST/StmtNodes.inc"
244+
245+
// Types.
246+
#define ABSTRACT_TYPE(CLASS, BASE)
247+
#define TYPE(CLASS, BASE) virtual bool Traverse##CLASS##Type(CLASS##Type *T);
248+
#include "clang/AST/TypeNodes.inc"
249+
250+
#define TYPE(CLASS, BASE) \
251+
bool WalkUpFrom##CLASS##Type(CLASS##Type *T); \
252+
virtual bool Visit##CLASS##Type(CLASS##Type *T) { return true; }
253+
#include "clang/AST/TypeNodes.inc"
254+
255+
// TypeLocs.
256+
#define ABSTRACT_TYPELOC(CLASS, BASE)
257+
#define TYPELOC(CLASS, BASE) \
258+
virtual bool Traverse##CLASS##TypeLoc(CLASS##TypeLoc TL);
259+
#include "clang/AST/TypeLocNodes.def"
260+
261+
#define TYPELOC(CLASS, BASE) \
262+
bool WalkUpFrom##CLASS##TypeLoc(CLASS##TypeLoc TL); \
263+
virtual bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TL) { return true; }
264+
#include "clang/AST/TypeLocNodes.def"
265+
};
266+
} // namespace clang
267+
268+
#endif // LLVM_CLANG_AST_DYNAMIC_RECURSIVE_AST_VISITOR_H

clang/lib/AST/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ add_clang_library(clangAST
5353
DeclOpenMP.cpp
5454
DeclPrinter.cpp
5555
DeclTemplate.cpp
56+
DynamicRecursiveASTVisitor.cpp
5657
ParentMapContext.cpp
5758
Expr.cpp
5859
ExprClassification.cpp

0 commit comments

Comments
 (0)