xref: /llvm-project/clang/lib/AST/DynamicRecursiveASTVisitor.cpp (revision 39a72be5e59c9a80570c1085a769593e2f26f054)
1 //=== DynamicRecursiveASTVisitor.cpp - Dynamic AST Visitor Implementation -===//
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 implements DynamicRecursiveASTVisitor in terms of the CRTP-based
10 // RecursiveASTVisitor.
11 //
12 //===----------------------------------------------------------------------===//
13 #include "clang/AST/DynamicRecursiveASTVisitor.h"
14 #include "clang/AST/RecursiveASTVisitor.h"
15 
16 using namespace clang;
17 
18 // The implementation of DRAV deserves some explanation:
19 //
20 // We want to implement DynamicRecursiveASTVisitor without having to inherit or
21 // reference RecursiveASTVisitor in any way in the header: if we instantiate
22 // RAV in the header, then every user of (or rather every file that uses) DRAV
23 // still has to instantiate a RAV, which gets us nowhere. Moreover, even just
24 // including RecursiveASTVisitor.h would probably cause some amount of slowdown
25 // because we'd have to parse a huge template. For these reasons, the fact that
26 // DRAV is implemented using a RAV is solely an implementation detail.
27 //
28 // As for the implementation itself, DRAV by default acts exactly like a RAV
29 // that overrides none of RAV's functions. There are two parts to this:
30 //
31 //   1. Any function in DRAV has to act like the corresponding function in RAV,
32 //      unless overridden by a derived class, of course.
33 //
34 //   2. Any call to a function by the RAV implementation that DRAV allows to be
35 //      overridden must be transformed to a virtual call on the user-provided
36 //      DRAV object: if some function in RAV calls e.g. TraverseCallExpr()
37 //      during traversal, then the derived class's TraverseCallExpr() must be
38 //      called (provided it overrides TraverseCallExpr()).
39 //
40 // The 'Impl' class is a helper that connects the two implementations; it is
41 // a wrapper around a reference to a DRAV that is itself a RecursiveASTVisitor.
42 // It overrides every function in RAV *that is virtual in DRAV* to perform a
43 // virtual call on its DRAV reference. This accomplishes point 2 above.
44 //
45 // Point 1 is accomplished by, first, having the base class implementation of
46 // each of the virtual functions construct an Impl object (which is actually
47 // just a no-op), passing in itself so that any virtual calls use the right
48 // vtable. Secondly, it then calls RAV's implementation of that same function
49 // *on Impl* (using a qualified call so that we actually call into the RAV
50 // implementation instead of Impl's version of that same function); this way,
51 // we both execute RAV's implementation for this function only and ensure that
52 // calls to subsequent functions call into Impl via CRTP (and Impl then calls
53 // back into DRAV and so on).
54 //
55 // While this ends up constructing a lot of Impl instances (almost one per
56 // function call), this doesn't really matter since Impl just holds a single
57 // pointer, and everything in this file should get inlined into all the DRAV
58 // functions here anyway.
59 //
60 //===----------------------------------------------------------------------===//
61 //
62 // The following illustrates how a call to an (overridden) function is actually
63 // resolved: given some class 'Derived' that derives from DRAV and overrides
64 // TraverseStmt(), if we are traversing some AST, and TraverseStmt() is called
65 // by the RAV implementation, the following happens:
66 //
67 //   1. Impl::TraverseStmt() overrides RAV::TraverseStmt() via CRTP, so the
68 //      former is called.
69 //
70 //   2. Impl::TraverseStmt() performs a virtual call to the visitor (which is
71 //      an instance to Derived), so Derived::TraverseStmt() is called.
72 //
73 //   End result: Derived::TraverseStmt() is executed.
74 //
75 // Suppose some other function, e.g. TraverseCallExpr(), which is NOT overridden
76 // by Derived is called, we get:
77 //
78 //   1. Impl::TraverseCallExpr() overrides RAV::TraverseCallExpr() via CRTP,
79 //      so the former is called.
80 //
81 //   2. Impl::TraverseCallExpr() performs a virtual call, but since Derived
82 //      does not override that function, DRAV::TraverseCallExpr() is called.
83 //
84 //   3. DRAV::TraverseCallExpr() creates a new instance of Impl, passing in
85 //      itself (this doesn't change that the pointer is an instance of Derived);
86 //      it then calls RAV::TraverseCallExpr() on the Impl object, which actually
87 //      ends up executing RAV's implementation because we used a qualified
88 //      function call.
89 //
90 //   End result: RAV::TraverseCallExpr() is executed,
91 namespace {
92 template <bool Const> struct Impl : RecursiveASTVisitor<Impl<Const>> {
93   DynamicRecursiveASTVisitorBase<Const> &Visitor;
94   Impl(DynamicRecursiveASTVisitorBase<Const> &Visitor) : Visitor(Visitor) {}
95 
96   bool shouldVisitTemplateInstantiations() const {
97     return Visitor.ShouldVisitTemplateInstantiations;
98   }
99 
100   bool shouldWalkTypesOfTypeLocs() const {
101     return Visitor.ShouldWalkTypesOfTypeLocs;
102   }
103 
104   bool shouldVisitImplicitCode() const {
105     return Visitor.ShouldVisitImplicitCode;
106   }
107 
108   bool shouldVisitLambdaBody() const { return Visitor.ShouldVisitLambdaBody; }
109 
110   // Supporting post-order would be very hard because of quirks of the
111   // RAV implementation that only work with CRTP. It also is only used
112   // by less than 5 visitors in the entire code base.
113   bool shouldTraversePostOrder() const { return false; }
114 
115   bool TraverseAST(ASTContext &AST) { return Visitor.TraverseAST(AST); }
116   bool TraverseAttr(Attr *At) { return Visitor.TraverseAttr(At); }
117   bool TraverseDecl(Decl *D) { return Visitor.TraverseDecl(D); }
118   bool TraverseType(QualType T) { return Visitor.TraverseType(T); }
119   bool TraverseTypeLoc(TypeLoc TL) { return Visitor.TraverseTypeLoc(TL); }
120   bool TraverseStmt(Stmt *S) { return Visitor.TraverseStmt(S); }
121 
122   bool TraverseConstructorInitializer(CXXCtorInitializer *Init) {
123     return Visitor.TraverseConstructorInitializer(Init);
124   }
125 
126   bool TraverseTemplateArgument(const TemplateArgument &Arg) {
127     return Visitor.TraverseTemplateArgument(Arg);
128   }
129 
130   bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc) {
131     return Visitor.TraverseTemplateArgumentLoc(ArgLoc);
132   }
133 
134   bool TraverseTemplateName(TemplateName Template) {
135     return Visitor.TraverseTemplateName(Template);
136   }
137 
138   bool TraverseObjCProtocolLoc(ObjCProtocolLoc ProtocolLoc) {
139     return Visitor.TraverseObjCProtocolLoc(ProtocolLoc);
140   }
141 
142   bool TraverseTypeConstraint(const TypeConstraint *C) {
143     return Visitor.TraverseTypeConstraint(C);
144   }
145   bool TraverseConceptRequirement(concepts::Requirement *R) {
146     return Visitor.TraverseConceptRequirement(R);
147   }
148   bool TraverseConceptTypeRequirement(concepts::TypeRequirement *R) {
149     return Visitor.TraverseConceptTypeRequirement(R);
150   }
151   bool TraverseConceptExprRequirement(concepts::ExprRequirement *R) {
152     return Visitor.TraverseConceptExprRequirement(R);
153   }
154   bool TraverseConceptNestedRequirement(concepts::NestedRequirement *R) {
155     return Visitor.TraverseConceptNestedRequirement(R);
156   }
157 
158   bool TraverseConceptReference(ConceptReference *CR) {
159     return Visitor.TraverseConceptReference(CR);
160   }
161 
162   bool TraverseCXXBaseSpecifier(const CXXBaseSpecifier &Base) {
163     return Visitor.TraverseCXXBaseSpecifier(Base);
164   }
165 
166   bool TraverseDeclarationNameInfo(DeclarationNameInfo NameInfo) {
167     return Visitor.TraverseDeclarationNameInfo(NameInfo);
168   }
169 
170   bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C,
171                              Expr *Init) {
172     return Visitor.TraverseLambdaCapture(LE, C, Init);
173   }
174 
175   bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS) {
176     return Visitor.TraverseNestedNameSpecifier(NNS);
177   }
178 
179   bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
180     return Visitor.TraverseNestedNameSpecifierLoc(NNS);
181   }
182 
183   bool VisitConceptReference(ConceptReference *CR) {
184     return Visitor.VisitConceptReference(CR);
185   }
186 
187   bool dataTraverseStmtPre(Stmt *S) { return Visitor.dataTraverseStmtPre(S); }
188   bool dataTraverseStmtPost(Stmt *S) { return Visitor.dataTraverseStmtPost(S); }
189 
190   // TraverseStmt() always passes in a queue, so we have no choice but to
191   // accept it as a parameter here.
192   bool dataTraverseNode(
193       Stmt *S,
194       typename RecursiveASTVisitor<Impl>::DataRecursionQueue * = nullptr) {
195     // But since we don't support postorder traversal, we don't need it, so
196     // simply discard it here. This way, derived classes don't need to worry
197     // about including it as a parameter that they never use.
198     return Visitor.dataTraverseNode(S);
199   }
200 
201   /// Visit a node.
202   bool VisitAttr(Attr *A) { return Visitor.VisitAttr(A); }
203   bool VisitDecl(Decl *D) { return Visitor.VisitDecl(D); }
204   bool VisitStmt(Stmt *S) { return Visitor.VisitStmt(S); }
205   bool VisitType(Type *T) { return Visitor.VisitType(T); }
206   bool VisitTypeLoc(TypeLoc TL) { return Visitor.VisitTypeLoc(TL); }
207 
208 #define DEF_TRAVERSE_TMPL_INST(kind)                                           \
209   bool TraverseTemplateInstantiations(kind##TemplateDecl *D) {                 \
210     return Visitor.TraverseTemplateInstantiations(D);                          \
211   }
212   DEF_TRAVERSE_TMPL_INST(Class)
213   DEF_TRAVERSE_TMPL_INST(Var)
214   DEF_TRAVERSE_TMPL_INST(Function)
215 #undef DEF_TRAVERSE_TMPL_INST
216 
217   // Decls.
218 #define ABSTRACT_DECL(DECL)
219 #define DECL(CLASS, BASE)                                                      \
220   bool Traverse##CLASS##Decl(CLASS##Decl *D) {                                 \
221     return Visitor.Traverse##CLASS##Decl(D);                                   \
222   }
223 #include "clang/AST/DeclNodes.inc"
224 
225 #define DECL(CLASS, BASE)                                                      \
226   bool Visit##CLASS##Decl(CLASS##Decl *D) {                                    \
227     return Visitor.Visit##CLASS##Decl(D);                                      \
228   }
229 #include "clang/AST/DeclNodes.inc"
230 
231   // Stmts.
232 #define ABSTRACT_STMT(STMT)
233 #define STMT(CLASS, PARENT)                                                    \
234   bool Traverse##CLASS(CLASS *S) { return Visitor.Traverse##CLASS(S); }
235 #include "clang/AST/StmtNodes.inc"
236 
237 #define STMT(CLASS, PARENT)                                                    \
238   bool Visit##CLASS(CLASS *S) { return Visitor.Visit##CLASS(S); }
239 #include "clang/AST/StmtNodes.inc"
240 
241   // Types.
242 #define ABSTRACT_TYPE(CLASS, BASE)
243 #define TYPE(CLASS, BASE)                                                      \
244   bool Traverse##CLASS##Type(CLASS##Type *T) {                                 \
245     return Visitor.Traverse##CLASS##Type(T);                                   \
246   }
247 #include "clang/AST/TypeNodes.inc"
248 
249 #define TYPE(CLASS, BASE)                                                      \
250   bool Visit##CLASS##Type(CLASS##Type *T) {                                    \
251     return Visitor.Visit##CLASS##Type(T);                                      \
252   }
253 #include "clang/AST/TypeNodes.inc"
254 
255   // TypeLocs.
256 #define ABSTRACT_TYPELOC(CLASS, BASE)
257 #define TYPELOC(CLASS, BASE)                                                   \
258   bool Traverse##CLASS##TypeLoc(CLASS##TypeLoc TL) {                           \
259     return Visitor.Traverse##CLASS##TypeLoc(TL);                               \
260   }
261 #include "clang/AST/TypeLocNodes.def"
262 
263 #define TYPELOC(CLASS, BASE)                                                   \
264   bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TL) {                              \
265     return Visitor.Visit##CLASS##TypeLoc(TL);                                  \
266   }
267 #include "clang/AST/TypeLocNodes.def"
268 };
269 } // namespace
270 
271 template <bool Const> void DynamicRecursiveASTVisitorBase<Const>::anchor() {}
272 
273 // Helper macros to forward a call to the base implementation since that
274 // ends up getting very verbose otherwise.
275 
276 // This calls the RecursiveASTVisitor implementation of the same function,
277 // stripping any 'const' that the DRAV implementation may have added since
278 // the RAV implementation largely doesn't use 'const'.
279 #define FORWARD_TO_BASE(Function, Type, RefOrPointer)                          \
280   template <bool Const>                                                        \
281   bool DynamicRecursiveASTVisitorBase<Const>::Function(                        \
282       MaybeConst<Type> RefOrPointer Param) {                                   \
283     return Impl<Const>(*this).RecursiveASTVisitor<Impl<Const>>::Function(      \
284         const_cast<Type RefOrPointer>(Param));                                 \
285   }
286 
287 // Same as 'FORWARD_TO_BASE', but doesn't change the parameter type in any way.
288 #define FORWARD_TO_BASE_EXACT(Function, Type)                                  \
289   template <bool Const>                                                        \
290   bool DynamicRecursiveASTVisitorBase<Const>::Function(Type Param) {           \
291     return Impl<Const>(*this).RecursiveASTVisitor<Impl<Const>>::Function(      \
292         Param);                                                                \
293   }
294 
295 FORWARD_TO_BASE(TraverseAST, ASTContext, &)
296 FORWARD_TO_BASE(TraverseAttr, Attr, *)
297 FORWARD_TO_BASE(TraverseConstructorInitializer, CXXCtorInitializer, *)
298 FORWARD_TO_BASE(TraverseDecl, Decl, *)
299 FORWARD_TO_BASE(TraverseStmt, Stmt, *)
300 FORWARD_TO_BASE(TraverseNestedNameSpecifier, NestedNameSpecifier, *)
301 FORWARD_TO_BASE(TraverseTemplateInstantiations, ClassTemplateDecl, *)
302 FORWARD_TO_BASE(TraverseTemplateInstantiations, VarTemplateDecl, *)
303 FORWARD_TO_BASE(TraverseTemplateInstantiations, FunctionTemplateDecl, *)
304 FORWARD_TO_BASE(TraverseConceptRequirement, concepts::Requirement, *)
305 FORWARD_TO_BASE(TraverseConceptTypeRequirement, concepts::TypeRequirement, *)
306 FORWARD_TO_BASE(TraverseConceptExprRequirement, concepts::ExprRequirement, *)
307 FORWARD_TO_BASE(TraverseConceptReference, ConceptReference, *)
308 FORWARD_TO_BASE(TraverseConceptNestedRequirement,
309                 concepts::NestedRequirement, *)
310 
311 FORWARD_TO_BASE_EXACT(TraverseCXXBaseSpecifier, const CXXBaseSpecifier &)
312 FORWARD_TO_BASE_EXACT(TraverseDeclarationNameInfo, DeclarationNameInfo)
313 FORWARD_TO_BASE_EXACT(TraverseTemplateArgument, const TemplateArgument &)
314 FORWARD_TO_BASE_EXACT(TraverseTemplateArguments, ArrayRef<TemplateArgument>)
315 FORWARD_TO_BASE_EXACT(TraverseTemplateArgumentLoc, const TemplateArgumentLoc &)
316 FORWARD_TO_BASE_EXACT(TraverseTemplateName, TemplateName)
317 FORWARD_TO_BASE_EXACT(TraverseType, QualType)
318 FORWARD_TO_BASE_EXACT(TraverseTypeLoc, TypeLoc)
319 FORWARD_TO_BASE_EXACT(TraverseTypeConstraint, const TypeConstraint *)
320 FORWARD_TO_BASE_EXACT(TraverseObjCProtocolLoc, ObjCProtocolLoc)
321 FORWARD_TO_BASE_EXACT(TraverseNestedNameSpecifierLoc, NestedNameSpecifierLoc)
322 
323 template <bool Const>
324 bool DynamicRecursiveASTVisitorBase<Const>::TraverseLambdaCapture(
325     MaybeConst<LambdaExpr> *LE, const LambdaCapture *C,
326     MaybeConst<Expr> *Init) {
327   return Impl<Const>(*this)
328       .RecursiveASTVisitor<Impl<Const>>::TraverseLambdaCapture(
329           const_cast<LambdaExpr *>(LE), C, const_cast<Expr *>(Init));
330 }
331 
332 template <bool Const>
333 bool DynamicRecursiveASTVisitorBase<Const>::dataTraverseNode(
334     MaybeConst<Stmt> *S) {
335   return Impl<Const>(*this).RecursiveASTVisitor<Impl<Const>>::dataTraverseNode(
336       const_cast<Stmt *>(S), nullptr);
337 }
338 
339 // Declare Traverse*() for and friends all concrete Decl classes.
340 #define ABSTRACT_DECL(DECL)
341 #define DECL(CLASS, BASE)                                                      \
342   FORWARD_TO_BASE(Traverse##CLASS##Decl, CLASS##Decl, *)                       \
343   FORWARD_TO_BASE(WalkUpFrom##CLASS##Decl, CLASS##Decl, *)
344 #include "clang/AST/DeclNodes.inc"
345 
346 // Declare Traverse*() and friends for all concrete Stmt classes.
347 #define ABSTRACT_STMT(STMT)
348 #define STMT(CLASS, PARENT) FORWARD_TO_BASE(Traverse##CLASS, CLASS, *)
349 #include "clang/AST/StmtNodes.inc"
350 
351 #define STMT(CLASS, PARENT) FORWARD_TO_BASE(WalkUpFrom##CLASS, CLASS, *)
352 #include "clang/AST/StmtNodes.inc"
353 
354 // Declare Traverse*() and friends for all concrete Type classes.
355 #define ABSTRACT_TYPE(CLASS, BASE)
356 #define TYPE(CLASS, BASE)                                                      \
357   FORWARD_TO_BASE(Traverse##CLASS##Type, CLASS##Type, *)                       \
358   FORWARD_TO_BASE(WalkUpFrom##CLASS##Type, CLASS##Type, *)
359 #include "clang/AST/TypeNodes.inc"
360 
361 #define ABSTRACT_TYPELOC(CLASS, BASE)
362 #define TYPELOC(CLASS, BASE)                                                   \
363   FORWARD_TO_BASE_EXACT(Traverse##CLASS##TypeLoc, CLASS##TypeLoc)
364 #include "clang/AST/TypeLocNodes.def"
365 
366 #define TYPELOC(CLASS, BASE)                                                   \
367   FORWARD_TO_BASE_EXACT(WalkUpFrom##CLASS##TypeLoc, CLASS##TypeLoc)
368 #include "clang/AST/TypeLocNodes.def"
369 
370 namespace clang {
371 template class DynamicRecursiveASTVisitorBase<false>;
372 template class DynamicRecursiveASTVisitorBase<true>;
373 } // namespace clang
374