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// Prefer to use this over RecursiveASTVisitor whenever possible.
14//
15//===----------------------------------------------------------------------===//
16#ifndef LLVM_CLANG_AST_DYNAMIC_RECURSIVE_AST_VISITOR_H
17#define LLVM_CLANG_AST_DYNAMIC_RECURSIVE_AST_VISITOR_H
18
19#include "clang/AST/Attr.h"
20#include "clang/AST/ExprConcepts.h"
21#include "clang/AST/TypeLoc.h"
22
23namespace clang {
24class ASTContext;
25
26/// Recursive AST visitor that supports extension via dynamic dispatch.
27///
28/// Like RecursiveASTVisitor, this class allows for traversal of arbitrarily
29/// complex ASTs. The main difference is that this uses virtual functions
30/// instead of CRTP, which greatly improves compile times of Clang itself,
31/// as well as binary size.
32///
33/// Instead of functions (e.g. shouldVisitImplicitCode()), this class
34/// uses member variables (e.g. ShouldVisitImplicitCode) to control
35/// visitation behaviour.
36///
37/// However, there is no support for overriding some of the less commonly
38/// used features of the RAV, such as WalkUpFromX or attribute traversal
39/// (attributes can still be traversed, but you can't change what happens
40/// when we traverse one).
41///
42/// The following is a list of RAV features that are NOT customisable:
43///
44/// - Visiting attributes,
45/// - Overriding WalkUpFromX,
46/// - Overriding getStmtChildren().
47///
48/// Furthermore, post-order traversal is not supported at all.
49///
50/// Prefer to use this over RecursiveASTVisitor unless you absolutely
51/// need to use one of the features listed above (e.g. overriding
52/// WalkUpFromX or post-order traversal).
53///
54/// \see RecursiveASTVisitor.
55template <bool IsConst> class DynamicRecursiveASTVisitorBase {
56protected:
57 template <typename ASTNode>
58 using MaybeConst = std::conditional_t<IsConst, const ASTNode, ASTNode>;
59
60public:
61 /// Whether this visitor should recurse into template instantiations.
62 bool ShouldVisitTemplateInstantiations = false;
63
64 /// Whether this visitor should recurse into the types of TypeLocs.
65 bool ShouldWalkTypesOfTypeLocs = true;
66
67 /// Whether this visitor should recurse into implicit code, e.g.
68 /// implicit constructors and destructors.
69 bool ShouldVisitImplicitCode = false;
70
71 /// Whether this visitor should recurse into lambda body.
72 bool ShouldVisitLambdaBody = true;
73
74protected:
75 DynamicRecursiveASTVisitorBase() = default;
76 DynamicRecursiveASTVisitorBase(DynamicRecursiveASTVisitorBase &&) = default;
77 DynamicRecursiveASTVisitorBase(const DynamicRecursiveASTVisitorBase &) =
78 default;
79 DynamicRecursiveASTVisitorBase &
80 operator=(DynamicRecursiveASTVisitorBase &&) = default;
81 DynamicRecursiveASTVisitorBase &
82 operator=(const DynamicRecursiveASTVisitorBase &) = default;
83
84public:
85 virtual void anchor();
86 virtual ~DynamicRecursiveASTVisitorBase() = default;
87
88 /// Recursively visits an entire AST, starting from the TranslationUnitDecl.
89 /// \returns false if visitation was terminated early.
90 virtual bool TraverseAST(MaybeConst<ASTContext> &AST);
91
92 /// Recursively visit an attribute, by dispatching to
93 /// Traverse*Attr() based on the argument's dynamic type.
94 ///
95 /// \returns false if the visitation was terminated early, true
96 /// otherwise (including when the argument is a Null type location).
97 virtual bool TraverseAttr(MaybeConst<Attr> *At);
98
99 /// Recursively visit a constructor initializer. This
100 /// automatically dispatches to another visitor for the initializer
101 /// expression, but not for the name of the initializer, so may
102 /// be overridden for clients that need access to the name.
103 ///
104 /// \returns false if the visitation was terminated early, true otherwise.
105 virtual bool
106 TraverseConstructorInitializer(MaybeConst<CXXCtorInitializer> *Init);
107
108 /// Recursively visit a base specifier. This can be overridden by a
109 /// subclass.
110 ///
111 /// \returns false if the visitation was terminated early, true otherwise.
112 virtual bool TraverseCXXBaseSpecifier(const CXXBaseSpecifier &Base);
113
114 /// Recursively visit a declaration, by dispatching to
115 /// Traverse*Decl() based on the argument's dynamic type.
116 ///
117 /// \returns false if the visitation was terminated early, true
118 /// otherwise (including when the argument is NULL).
119 virtual bool TraverseDecl(MaybeConst<Decl> *D);
120
121 /// Recursively visit a name with its location information.
122 ///
123 /// \returns false if the visitation was terminated early, true otherwise.
124 virtual bool TraverseDeclarationNameInfo(DeclarationNameInfo NameInfo);
125
126 /// Recursively visit a lambda capture. \c Init is the expression that
127 /// will be used to initialize the capture.
128 ///
129 /// \returns false if the visitation was terminated early, true otherwise.
130 virtual bool TraverseLambdaCapture(MaybeConst<LambdaExpr> *LE,
131 const LambdaCapture *C,
132 MaybeConst<Expr> *Init);
133
134 /// Recursively visit a C++ nested-name-specifier.
135 ///
136 /// \returns false if the visitation was terminated early, true otherwise.
137 virtual bool
138 TraverseNestedNameSpecifier(MaybeConst<NestedNameSpecifier> *NNS);
139
140 /// Recursively visit a C++ nested-name-specifier with location
141 /// information.
142 ///
143 /// \returns false if the visitation was terminated early, true otherwise.
144 virtual bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS);
145
146 /// Recursively visit a statement or expression, by
147 /// dispatching to Traverse*() based on the argument's dynamic type.
148 ///
149 /// \returns false if the visitation was terminated early, true
150 /// otherwise (including when the argument is nullptr).
151 virtual bool TraverseStmt(MaybeConst<Stmt> *S);
152
153 /// Recursively visit a template argument and dispatch to the
154 /// appropriate method for the argument type.
155 ///
156 /// \returns false if the visitation was terminated early, true otherwise.
157 // FIXME: migrate callers to TemplateArgumentLoc instead.
158 virtual bool TraverseTemplateArgument(const TemplateArgument &Arg);
159
160 /// Recursively visit a template argument location and dispatch to the
161 /// appropriate method for the argument type.
162 ///
163 /// \returns false if the visitation was terminated early, true otherwise.
164 virtual bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc);
165
166 /// Recursively visit a set of template arguments.
167 ///
168 /// \returns false if the visitation was terminated early, true otherwise.
169 // FIXME: take a TemplateArgumentLoc* (or TemplateArgumentListInfo) instead.
170 // Not virtual for now because no-one overrides it.
171 bool TraverseTemplateArguments(ArrayRef<TemplateArgument> Args);
172
173 /// Recursively visit a template name and dispatch to the
174 /// appropriate method.
175 ///
176 /// \returns false if the visitation was terminated early, true otherwise.
177 virtual bool TraverseTemplateName(TemplateName Template);
178
179 /// Recursively visit a type, by dispatching to
180 /// Traverse*Type() based on the argument's getTypeClass() property.
181 ///
182 /// \returns false if the visitation was terminated early, true
183 /// otherwise (including when the argument is a Null type).
184 virtual bool TraverseType(QualType T);
185
186 /// Recursively visit a type with location, by dispatching to
187 /// Traverse*TypeLoc() based on the argument type's getTypeClass() property.
188 ///
189 /// \returns false if the visitation was terminated early, true
190 /// otherwise (including when the argument is a Null type location).
191 virtual bool TraverseTypeLoc(TypeLoc TL);
192
193 /// Recursively visit an Objective-C protocol reference with location
194 /// information.
195 ///
196 /// \returns false if the visitation was terminated early, true otherwise.
197 virtual bool TraverseObjCProtocolLoc(ObjCProtocolLoc ProtocolLoc);
198
199 /// Traverse a concept (requirement).
200 virtual bool TraverseTypeConstraint(const TypeConstraint *C);
201 virtual bool TraverseConceptRequirement(MaybeConst<concepts::Requirement> *R);
202
203 virtual bool
204 TraverseConceptTypeRequirement(MaybeConst<concepts::TypeRequirement> *R);
205
206 virtual bool
207 TraverseConceptExprRequirement(MaybeConst<concepts::ExprRequirement> *R);
208
209 virtual bool
210 TraverseConceptNestedRequirement(MaybeConst<concepts::NestedRequirement> *R);
211
212 virtual bool TraverseConceptReference(MaybeConst<ConceptReference> *CR);
213 virtual bool VisitConceptReference(MaybeConst<ConceptReference> *CR) {
214 return true;
215 }
216
217 /// Visit a node.
218 virtual bool VisitAttr(MaybeConst<Attr> *A) { return true; }
219 virtual bool VisitDecl(MaybeConst<Decl> *D) { return true; }
220 virtual bool VisitStmt(MaybeConst<Stmt> *S) { return true; }
221 virtual bool VisitType(MaybeConst<Type> *T) { return true; }
222 virtual bool VisitTypeLoc(TypeLoc TL) { return true; }
223
224 /// Walk up from a node.
225 bool WalkUpFromDecl(MaybeConst<Decl> *D) { return VisitDecl(D); }
226 bool WalkUpFromStmt(MaybeConst<Stmt> *S) { return VisitStmt(S); }
227 bool WalkUpFromType(MaybeConst<Type> *T) { return VisitType(T); }
228 bool WalkUpFromTypeLoc(TypeLoc TL) { return VisitTypeLoc(TL); }
229
230 /// Invoked before visiting a statement or expression via data recursion.
231 ///
232 /// \returns false to skip visiting the node, true otherwise.
233 virtual bool dataTraverseStmtPre(MaybeConst<Stmt> *S) { return true; }
234
235 /// Invoked after visiting a statement or expression via data recursion.
236 /// This is not invoked if the previously invoked \c dataTraverseStmtPre
237 /// returned false.
238 ///
239 /// \returns false if the visitation was terminated early, true otherwise.
240 virtual bool dataTraverseStmtPost(MaybeConst<Stmt> *S) { return true; }
241 virtual bool dataTraverseNode(MaybeConst<Stmt> *S);
242
243#define DEF_TRAVERSE_TMPL_INST(kind) \
244 virtual bool TraverseTemplateInstantiations( \
245 MaybeConst<kind##TemplateDecl> *D);
246 DEF_TRAVERSE_TMPL_INST(Class)
247 DEF_TRAVERSE_TMPL_INST(Var)
248 DEF_TRAVERSE_TMPL_INST(Function)
249#undef DEF_TRAVERSE_TMPL_INST
250
251 // Decls.
252#define ABSTRACT_DECL(DECL)
253#define DECL(CLASS, BASE) \
254 bool WalkUpFrom##CLASS##Decl(MaybeConst<CLASS##Decl> *D); \
255 virtual bool Traverse##CLASS##Decl(MaybeConst<CLASS##Decl> *D);
256#include "clang/AST/DeclNodes.inc"
257
258#define DECL(CLASS, BASE) \
259 virtual bool Visit##CLASS##Decl(MaybeConst<CLASS##Decl> *D) { return true; }
260#include "clang/AST/DeclNodes.inc"
261
262 // Stmts.
263#define ABSTRACT_STMT(STMT)
264#define STMT(CLASS, PARENT) virtual bool Traverse##CLASS(MaybeConst<CLASS> *S);
265#include "clang/AST/StmtNodes.inc"
266
267#define STMT(CLASS, PARENT) \
268 bool WalkUpFrom##CLASS(MaybeConst<CLASS> *S); \
269 virtual bool Visit##CLASS(MaybeConst<CLASS> *S) { return true; }
270#include "clang/AST/StmtNodes.inc"
271
272 // Types.
273#define ABSTRACT_TYPE(CLASS, BASE)
274#define TYPE(CLASS, BASE) \
275 bool WalkUpFrom##CLASS##Type(MaybeConst<CLASS##Type> *T); \
276 virtual bool Traverse##CLASS##Type(MaybeConst<CLASS##Type> *T);
277#include "clang/AST/TypeNodes.inc"
278
279#define TYPE(CLASS, BASE) \
280 virtual bool Visit##CLASS##Type(MaybeConst<CLASS##Type> *T) { return true; }
281#include "clang/AST/TypeNodes.inc"
282
283 // TypeLocs.
284#define ABSTRACT_TYPELOC(CLASS, BASE)
285#define TYPELOC(CLASS, BASE) \
286 virtual bool Traverse##CLASS##TypeLoc(CLASS##TypeLoc TL);
287#include "clang/AST/TypeLocNodes.def"
288
289#define TYPELOC(CLASS, BASE) \
290 bool WalkUpFrom##CLASS##TypeLoc(CLASS##TypeLoc TL); \
291 virtual bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TL) { return true; }
292#include "clang/AST/TypeLocNodes.def"
293};
294
295extern template class DynamicRecursiveASTVisitorBase<false>;
296extern template class DynamicRecursiveASTVisitorBase<true>;
297
298using DynamicRecursiveASTVisitor =
299 DynamicRecursiveASTVisitorBase</*Const=*/false>;
300using ConstDynamicRecursiveASTVisitor =
301 DynamicRecursiveASTVisitorBase</*Const=*/true>;
302} // namespace clang
303
304#endif // LLVM_CLANG_AST_DYNAMIC_RECURSIVE_AST_VISITOR_H
305

source code of clang/include/clang/AST/DynamicRecursiveASTVisitor.h