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