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