xref: /freebsd/contrib/llvm-project/clang/include/clang/AST/DynamicRecursiveASTVisitor.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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 
23 namespace clang {
24 class 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.
55 template <bool IsConst> class DynamicRecursiveASTVisitorBase {
56 protected:
57   template <typename ASTNode>
58   using MaybeConst = std::conditional_t<IsConst, const ASTNode, ASTNode>;
59 
60 public:
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 
74 protected:
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 
84 public:
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);
VisitConceptReference(MaybeConst<ConceptReference> * CR)213   virtual bool VisitConceptReference(MaybeConst<ConceptReference> *CR) {
214     return true;
215   }
216 
217   /// Visit a node.
VisitAttr(MaybeConst<Attr> * A)218   virtual bool VisitAttr(MaybeConst<Attr> *A) { return true; }
VisitDecl(MaybeConst<Decl> * D)219   virtual bool VisitDecl(MaybeConst<Decl> *D) { return true; }
VisitStmt(MaybeConst<Stmt> * S)220   virtual bool VisitStmt(MaybeConst<Stmt> *S) { return true; }
VisitType(MaybeConst<Type> * T)221   virtual bool VisitType(MaybeConst<Type> *T) { return true; }
VisitTypeLoc(TypeLoc TL)222   virtual bool VisitTypeLoc(TypeLoc TL) { return true; }
223 
224   /// Walk up from a node.
WalkUpFromDecl(MaybeConst<Decl> * D)225   bool WalkUpFromDecl(MaybeConst<Decl> *D) { return VisitDecl(D); }
WalkUpFromStmt(MaybeConst<Stmt> * S)226   bool WalkUpFromStmt(MaybeConst<Stmt> *S) { return VisitStmt(S); }
WalkUpFromType(MaybeConst<Type> * T)227   bool WalkUpFromType(MaybeConst<Type> *T) { return VisitType(T); }
WalkUpFromTypeLoc(TypeLoc TL)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.
dataTraverseStmtPre(MaybeConst<Stmt> * S)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.
dataTraverseStmtPost(MaybeConst<Stmt> * S)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 
295 extern template class DynamicRecursiveASTVisitorBase<false>;
296 extern template class DynamicRecursiveASTVisitorBase<true>;
297 
298 using DynamicRecursiveASTVisitor =
299     DynamicRecursiveASTVisitorBase</*Const=*/false>;
300 using ConstDynamicRecursiveASTVisitor =
301     DynamicRecursiveASTVisitorBase</*Const=*/true>;
302 } // namespace clang
303 
304 #endif // LLVM_CLANG_AST_DYNAMIC_RECURSIVE_AST_VISITOR_H
305