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