| 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 | |