| 1 | //===--- RecursiveASTVisitor.h - Recursive AST Visitor ----------*- C++ -*-===// |
| 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 defines the RecursiveASTVisitor interface, which recursively |
| 10 | // traverses the entire AST. |
| 11 | // |
| 12 | //===----------------------------------------------------------------------===// |
| 13 | #ifndef LLVM_CLANG_AST_RECURSIVEASTVISITOR_H |
| 14 | #define LLVM_CLANG_AST_RECURSIVEASTVISITOR_H |
| 15 | |
| 16 | #include "clang/AST/ASTConcept.h" |
| 17 | #include "clang/AST/Attr.h" |
| 18 | #include "clang/AST/Decl.h" |
| 19 | #include "clang/AST/DeclBase.h" |
| 20 | #include "clang/AST/DeclCXX.h" |
| 21 | #include "clang/AST/DeclFriend.h" |
| 22 | #include "clang/AST/DeclObjC.h" |
| 23 | #include "clang/AST/DeclOpenACC.h" |
| 24 | #include "clang/AST/DeclOpenMP.h" |
| 25 | #include "clang/AST/DeclTemplate.h" |
| 26 | #include "clang/AST/DeclarationName.h" |
| 27 | #include "clang/AST/Expr.h" |
| 28 | #include "clang/AST/ExprCXX.h" |
| 29 | #include "clang/AST/ExprConcepts.h" |
| 30 | #include "clang/AST/ExprObjC.h" |
| 31 | #include "clang/AST/ExprOpenMP.h" |
| 32 | #include "clang/AST/LambdaCapture.h" |
| 33 | #include "clang/AST/NestedNameSpecifier.h" |
| 34 | #include "clang/AST/OpenACCClause.h" |
| 35 | #include "clang/AST/OpenMPClause.h" |
| 36 | #include "clang/AST/Stmt.h" |
| 37 | #include "clang/AST/StmtCXX.h" |
| 38 | #include "clang/AST/StmtObjC.h" |
| 39 | #include "clang/AST/StmtOpenACC.h" |
| 40 | #include "clang/AST/StmtOpenMP.h" |
| 41 | #include "clang/AST/StmtSYCL.h" |
| 42 | #include "clang/AST/TemplateBase.h" |
| 43 | #include "clang/AST/TemplateName.h" |
| 44 | #include "clang/AST/Type.h" |
| 45 | #include "clang/AST/TypeLoc.h" |
| 46 | #include "clang/Basic/LLVM.h" |
| 47 | #include "clang/Basic/OpenMPKinds.h" |
| 48 | #include "clang/Basic/Specifiers.h" |
| 49 | #include "llvm/ADT/PointerIntPair.h" |
| 50 | #include "llvm/ADT/SmallVector.h" |
| 51 | #include "llvm/Support/Casting.h" |
| 52 | #include <algorithm> |
| 53 | #include <cstddef> |
| 54 | #include <type_traits> |
| 55 | |
| 56 | namespace clang { |
| 57 | |
| 58 | // A helper macro to implement short-circuiting when recursing. It |
| 59 | // invokes CALL_EXPR, which must be a method call, on the derived |
| 60 | // object (s.t. a user of RecursiveASTVisitor can override the method |
| 61 | // in CALL_EXPR). |
| 62 | #define TRY_TO(CALL_EXPR) \ |
| 63 | do { \ |
| 64 | if (!getDerived().CALL_EXPR) \ |
| 65 | return false; \ |
| 66 | } while (false) |
| 67 | |
| 68 | namespace detail { |
| 69 | |
| 70 | template <typename T, typename U> |
| 71 | struct has_same_member_pointer_type : std::false_type {}; |
| 72 | template <typename T, typename U, typename R, typename... P> |
| 73 | struct has_same_member_pointer_type<R (T::*)(P...), R (U::*)(P...)> |
| 74 | : std::true_type {}; |
| 75 | |
| 76 | /// Returns true if and only if \p FirstMethodPtr and \p SecondMethodPtr |
| 77 | /// are pointers to the same non-static member function. |
| 78 | template <typename FirstMethodPtrTy, typename SecondMethodPtrTy> |
| 79 | LLVM_ATTRIBUTE_ALWAYS_INLINE LLVM_ATTRIBUTE_NODEBUG auto |
| 80 | isSameMethod([[maybe_unused]] FirstMethodPtrTy FirstMethodPtr, |
| 81 | [[maybe_unused]] SecondMethodPtrTy SecondMethodPtr) |
| 82 | -> bool { |
| 83 | if constexpr (has_same_member_pointer_type<FirstMethodPtrTy, |
| 84 | SecondMethodPtrTy>::value) |
| 85 | return FirstMethodPtr == SecondMethodPtr; |
| 86 | return false; |
| 87 | } |
| 88 | |
| 89 | } // end namespace detail |
| 90 | |
| 91 | /// A class that does preorder or postorder |
| 92 | /// depth-first traversal on the entire Clang AST and visits each node. |
| 93 | /// |
| 94 | /// This class performs three distinct tasks: |
| 95 | /// 1. traverse the AST (i.e. go to each node); |
| 96 | /// 2. at a given node, walk up the class hierarchy, starting from |
| 97 | /// the node's dynamic type, until the top-most class (e.g. Stmt, |
| 98 | /// Decl, or Type) is reached. |
| 99 | /// 3. given a (node, class) combination, where 'class' is some base |
| 100 | /// class of the dynamic type of 'node', call a user-overridable |
| 101 | /// function to actually visit the node. |
| 102 | /// |
| 103 | /// These tasks are done by three groups of methods, respectively: |
| 104 | /// 1. TraverseDecl(Decl *x) does task #1. It is the entry point |
| 105 | /// for traversing an AST rooted at x. This method simply |
| 106 | /// dispatches (i.e. forwards) to TraverseFoo(Foo *x) where Foo |
| 107 | /// is the dynamic type of *x, which calls WalkUpFromFoo(x) and |
| 108 | /// then recursively visits the child nodes of x. |
| 109 | /// TraverseStmt(Stmt *x) and TraverseType(QualType x) work |
| 110 | /// similarly. |
| 111 | /// 2. WalkUpFromFoo(Foo *x) does task #2. It does not try to visit |
| 112 | /// any child node of x. Instead, it first calls WalkUpFromBar(x) |
| 113 | /// where Bar is the direct parent class of Foo (unless Foo has |
| 114 | /// no parent), and then calls VisitFoo(x) (see the next list item). |
| 115 | /// 3. VisitFoo(Foo *x) does task #3. |
| 116 | /// |
| 117 | /// These three method groups are tiered (Traverse* > WalkUpFrom* > |
| 118 | /// Visit*). A method (e.g. Traverse*) may call methods from the same |
| 119 | /// tier (e.g. other Traverse*) or one tier lower (e.g. WalkUpFrom*). |
| 120 | /// It may not call methods from a higher tier. |
| 121 | /// |
| 122 | /// Note that since WalkUpFromFoo() calls WalkUpFromBar() (where Bar |
| 123 | /// is Foo's super class) before calling VisitFoo(), the result is |
| 124 | /// that the Visit*() methods for a given node are called in the |
| 125 | /// top-down order (e.g. for a node of type NamespaceDecl, the order will |
| 126 | /// be VisitDecl(), VisitNamedDecl(), and then VisitNamespaceDecl()). |
| 127 | /// |
| 128 | /// This scheme guarantees that all Visit*() calls for the same AST |
| 129 | /// node are grouped together. In other words, Visit*() methods for |
| 130 | /// different nodes are never interleaved. |
| 131 | /// |
| 132 | /// Clients of this visitor should subclass the visitor (providing |
| 133 | /// themselves as the template argument, using the curiously recurring |
| 134 | /// template pattern) and override any of the Traverse*, WalkUpFrom*, |
| 135 | /// and Visit* methods for declarations, types, statements, |
| 136 | /// expressions, or other AST nodes where the visitor should customize |
| 137 | /// behavior. Most users only need to override Visit*. Advanced |
| 138 | /// users may override Traverse* and WalkUpFrom* to implement custom |
| 139 | /// traversal strategies. Returning false from one of these overridden |
| 140 | /// functions will abort the entire traversal. |
| 141 | /// |
| 142 | /// By default, this visitor tries to visit every part of the explicit |
| 143 | /// source code exactly once. The default policy towards templates |
| 144 | /// is to descend into the 'pattern' class or function body, not any |
| 145 | /// explicit or implicit instantiations. Explicit specializations |
| 146 | /// are still visited, and the patterns of partial specializations |
| 147 | /// are visited separately. This behavior can be changed by |
| 148 | /// overriding shouldVisitTemplateInstantiations() in the derived class |
| 149 | /// to return true, in which case all known implicit and explicit |
| 150 | /// instantiations will be visited at the same time as the pattern |
| 151 | /// from which they were produced. |
| 152 | /// |
| 153 | /// By default, this visitor preorder traverses the AST. If postorder traversal |
| 154 | /// is needed, the \c shouldTraversePostOrder method needs to be overridden |
| 155 | /// to return \c true. |
| 156 | template <typename Derived> class RecursiveASTVisitor { |
| 157 | public: |
| 158 | /// A queue used for performing data recursion over statements. |
| 159 | /// Parameters involving this type are used to implement data |
| 160 | /// recursion over Stmts and Exprs within this class, and should |
| 161 | /// typically not be explicitly specified by derived classes. |
| 162 | /// The bool bit indicates whether the statement has been traversed or not. |
| 163 | typedef SmallVectorImpl<llvm::PointerIntPair<Stmt *, 1, bool>> |
| 164 | DataRecursionQueue; |
| 165 | |
| 166 | /// Return a reference to the derived class. |
| 167 | Derived &getDerived() { return *static_cast<Derived *>(this); } |
| 168 | |
| 169 | /// Return whether this visitor should recurse into |
| 170 | /// template instantiations. |
| 171 | bool shouldVisitTemplateInstantiations() const { return false; } |
| 172 | |
| 173 | /// Return whether this visitor should recurse into the types of |
| 174 | /// TypeLocs. |
| 175 | bool shouldWalkTypesOfTypeLocs() const { return true; } |
| 176 | |
| 177 | /// Return whether this visitor should recurse into implicit |
| 178 | /// code, e.g., implicit constructors and destructors. |
| 179 | bool shouldVisitImplicitCode() const { return false; } |
| 180 | |
| 181 | /// Return whether this visitor should recurse into lambda body |
| 182 | bool shouldVisitLambdaBody() const { return true; } |
| 183 | |
| 184 | /// Return whether this visitor should traverse post-order. |
| 185 | bool shouldTraversePostOrder() const { return false; } |
| 186 | |
| 187 | /// Recursively visits an entire AST, starting from the TranslationUnitDecl. |
| 188 | /// \returns false if visitation was terminated early. |
| 189 | bool TraverseAST(ASTContext &AST) { |
| 190 | // Currently just an alias for TraverseDecl(TUDecl), but kept in case |
| 191 | // we change the implementation again. |
| 192 | return getDerived().TraverseDecl(AST.getTranslationUnitDecl()); |
| 193 | } |
| 194 | |
| 195 | /// Recursively visit a statement or expression, by |
| 196 | /// dispatching to Traverse*() based on the argument's dynamic type. |
| 197 | /// |
| 198 | /// \returns false if the visitation was terminated early, true |
| 199 | /// otherwise (including when the argument is nullptr). |
| 200 | bool TraverseStmt(Stmt *S, DataRecursionQueue *Queue = nullptr); |
| 201 | |
| 202 | /// Invoked before visiting a statement or expression via data recursion. |
| 203 | /// |
| 204 | /// \returns false to skip visiting the node, true otherwise. |
| 205 | bool dataTraverseStmtPre(Stmt *S) { return true; } |
| 206 | |
| 207 | /// Invoked after visiting a statement or expression via data recursion. |
| 208 | /// This is not invoked if the previously invoked \c dataTraverseStmtPre |
| 209 | /// returned false. |
| 210 | /// |
| 211 | /// \returns false if the visitation was terminated early, true otherwise. |
| 212 | bool dataTraverseStmtPost(Stmt *S) { return true; } |
| 213 | |
| 214 | /// Recursively visit a type, by dispatching to |
| 215 | /// Traverse*Type() based on the argument's getTypeClass() property. |
| 216 | /// |
| 217 | /// \returns false if the visitation was terminated early, true |
| 218 | /// otherwise (including when the argument is a Null type). |
| 219 | bool TraverseType(QualType T); |
| 220 | |
| 221 | /// Recursively visit a type with location, by dispatching to |
| 222 | /// Traverse*TypeLoc() based on the argument type's getTypeClass() property. |
| 223 | /// |
| 224 | /// \returns false if the visitation was terminated early, true |
| 225 | /// otherwise (including when the argument is a Null type location). |
| 226 | bool TraverseTypeLoc(TypeLoc TL); |
| 227 | |
| 228 | /// Recursively visit an attribute, by dispatching to |
| 229 | /// Traverse*Attr() based on the argument's dynamic type. |
| 230 | /// |
| 231 | /// \returns false if the visitation was terminated early, true |
| 232 | /// otherwise (including when the argument is a Null type location). |
| 233 | bool TraverseAttr(Attr *At); |
| 234 | |
| 235 | /// Recursively visit a declaration, by dispatching to |
| 236 | /// Traverse*Decl() based on the argument's dynamic type. |
| 237 | /// |
| 238 | /// \returns false if the visitation was terminated early, true |
| 239 | /// otherwise (including when the argument is NULL). |
| 240 | bool TraverseDecl(Decl *D); |
| 241 | |
| 242 | /// Recursively visit a C++ nested-name-specifier. |
| 243 | /// |
| 244 | /// \returns false if the visitation was terminated early, true otherwise. |
| 245 | bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS); |
| 246 | |
| 247 | /// Recursively visit a C++ nested-name-specifier with location |
| 248 | /// information. |
| 249 | /// |
| 250 | /// \returns false if the visitation was terminated early, true otherwise. |
| 251 | bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS); |
| 252 | |
| 253 | /// Recursively visit a name with its location information. |
| 254 | /// |
| 255 | /// \returns false if the visitation was terminated early, true otherwise. |
| 256 | bool TraverseDeclarationNameInfo(DeclarationNameInfo NameInfo); |
| 257 | |
| 258 | /// Recursively visit a template name and dispatch to the |
| 259 | /// appropriate method. |
| 260 | /// |
| 261 | /// \returns false if the visitation was terminated early, true otherwise. |
| 262 | bool TraverseTemplateName(TemplateName Template); |
| 263 | |
| 264 | /// Recursively visit a template argument and dispatch to the |
| 265 | /// appropriate method for the argument type. |
| 266 | /// |
| 267 | /// \returns false if the visitation was terminated early, true otherwise. |
| 268 | // FIXME: migrate callers to TemplateArgumentLoc instead. |
| 269 | bool TraverseTemplateArgument(const TemplateArgument &Arg); |
| 270 | |
| 271 | /// Recursively visit a template argument location and dispatch to the |
| 272 | /// appropriate method for the argument type. |
| 273 | /// |
| 274 | /// \returns false if the visitation was terminated early, true otherwise. |
| 275 | bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc); |
| 276 | |
| 277 | /// Recursively visit a set of template arguments. |
| 278 | /// This can be overridden by a subclass, but it's not expected that |
| 279 | /// will be needed -- this visitor always dispatches to another. |
| 280 | /// |
| 281 | /// \returns false if the visitation was terminated early, true otherwise. |
| 282 | // FIXME: take a TemplateArgumentLoc* (or TemplateArgumentListInfo) instead. |
| 283 | bool TraverseTemplateArguments(ArrayRef<TemplateArgument> Args); |
| 284 | |
| 285 | /// Recursively visit a base specifier. This can be overridden by a |
| 286 | /// subclass. |
| 287 | /// |
| 288 | /// \returns false if the visitation was terminated early, true otherwise. |
| 289 | bool TraverseCXXBaseSpecifier(const CXXBaseSpecifier &Base); |
| 290 | |
| 291 | /// Recursively visit a constructor initializer. This |
| 292 | /// automatically dispatches to another visitor for the initializer |
| 293 | /// expression, but not for the name of the initializer, so may |
| 294 | /// be overridden for clients that need access to the name. |
| 295 | /// |
| 296 | /// \returns false if the visitation was terminated early, true otherwise. |
| 297 | bool TraverseConstructorInitializer(CXXCtorInitializer *Init); |
| 298 | |
| 299 | /// Recursively visit a lambda capture. \c Init is the expression that |
| 300 | /// will be used to initialize the capture. |
| 301 | /// |
| 302 | /// \returns false if the visitation was terminated early, true otherwise. |
| 303 | bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C, |
| 304 | Expr *Init); |
| 305 | |
| 306 | /// Recursively visit the syntactic or semantic form of an |
| 307 | /// initialization list. |
| 308 | /// |
| 309 | /// \returns false if the visitation was terminated early, true otherwise. |
| 310 | bool TraverseSynOrSemInitListExpr(InitListExpr *S, |
| 311 | DataRecursionQueue *Queue = nullptr); |
| 312 | |
| 313 | /// Recursively visit an Objective-C protocol reference with location |
| 314 | /// information. |
| 315 | /// |
| 316 | /// \returns false if the visitation was terminated early, true otherwise. |
| 317 | bool TraverseObjCProtocolLoc(ObjCProtocolLoc ProtocolLoc); |
| 318 | |
| 319 | /// Recursively visit concept reference with location information. |
| 320 | /// |
| 321 | /// \returns false if the visitation was terminated early, true otherwise. |
| 322 | bool TraverseConceptReference(ConceptReference *CR); |
| 323 | |
| 324 | // Visit concept reference. |
| 325 | bool VisitConceptReference(ConceptReference *CR) { return true; } |
| 326 | // ---- Methods on Attrs ---- |
| 327 | |
| 328 | // Visit an attribute. |
| 329 | bool VisitAttr(Attr *A) { return true; } |
| 330 | |
| 331 | // Declare Traverse* and empty Visit* for all Attr classes. |
| 332 | #define ATTR_VISITOR_DECLS_ONLY |
| 333 | #include "clang/AST/AttrVisitor.inc" |
| 334 | #undef ATTR_VISITOR_DECLS_ONLY |
| 335 | |
| 336 | // ---- Methods on Stmts ---- |
| 337 | |
| 338 | Stmt::child_range getStmtChildren(Stmt *S) { return S->children(); } |
| 339 | |
| 340 | private: |
| 341 | // Traverse the given statement. If the most-derived traverse function takes a |
| 342 | // data recursion queue, pass it on; otherwise, discard it. Note that the |
| 343 | // first branch of this conditional must compile whether or not the derived |
| 344 | // class can take a queue, so if we're taking the second arm, make the first |
| 345 | // arm call our function rather than the derived class version. |
| 346 | #define TRAVERSE_STMT_BASE(NAME, CLASS, VAR, QUEUE) \ |
| 347 | (::clang::detail::has_same_member_pointer_type< \ |
| 348 | decltype(&RecursiveASTVisitor::Traverse##NAME), \ |
| 349 | decltype(&Derived::Traverse##NAME)>::value \ |
| 350 | ? static_cast<std::conditional_t< \ |
| 351 | ::clang::detail::has_same_member_pointer_type< \ |
| 352 | decltype(&RecursiveASTVisitor::Traverse##NAME), \ |
| 353 | decltype(&Derived::Traverse##NAME)>::value, \ |
| 354 | Derived &, RecursiveASTVisitor &>>(*this) \ |
| 355 | .Traverse##NAME(static_cast<CLASS *>(VAR), QUEUE) \ |
| 356 | : getDerived().Traverse##NAME(static_cast<CLASS *>(VAR))) |
| 357 | |
| 358 | // Try to traverse the given statement, or enqueue it if we're performing data |
| 359 | // recursion in the middle of traversing another statement. Can only be called |
| 360 | // from within a DEF_TRAVERSE_STMT body or similar context. |
| 361 | #define TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S) \ |
| 362 | do { \ |
| 363 | if (!TRAVERSE_STMT_BASE(Stmt, Stmt, S, Queue)) \ |
| 364 | return false; \ |
| 365 | } while (false) |
| 366 | |
| 367 | public: |
| 368 | // Declare Traverse*() for all concrete Stmt classes. |
| 369 | #define ABSTRACT_STMT(STMT) |
| 370 | #define STMT(CLASS, PARENT) \ |
| 371 | bool Traverse##CLASS(CLASS *S, DataRecursionQueue *Queue = nullptr); |
| 372 | #include "clang/AST/StmtNodes.inc" |
| 373 | // The above header #undefs ABSTRACT_STMT and STMT upon exit. |
| 374 | |
| 375 | // Define WalkUpFrom*() and empty Visit*() for all Stmt classes. |
| 376 | bool WalkUpFromStmt(Stmt *S) { return getDerived().VisitStmt(S); } |
| 377 | bool VisitStmt(Stmt *S) { return true; } |
| 378 | #define STMT(CLASS, PARENT) \ |
| 379 | bool WalkUpFrom##CLASS(CLASS *S) { \ |
| 380 | TRY_TO(WalkUpFrom##PARENT(S)); \ |
| 381 | TRY_TO(Visit##CLASS(S)); \ |
| 382 | return true; \ |
| 383 | } \ |
| 384 | bool Visit##CLASS(CLASS *S) { return true; } |
| 385 | #include "clang/AST/StmtNodes.inc" |
| 386 | |
| 387 | // ---- Methods on Types ---- |
| 388 | // FIXME: revamp to take TypeLoc's rather than Types. |
| 389 | |
| 390 | // Declare Traverse*() for all concrete Type classes. |
| 391 | #define ABSTRACT_TYPE(CLASS, BASE) |
| 392 | #define TYPE(CLASS, BASE) bool Traverse##CLASS##Type(CLASS##Type *T); |
| 393 | #include "clang/AST/TypeNodes.inc" |
| 394 | // The above header #undefs ABSTRACT_TYPE and TYPE upon exit. |
| 395 | |
| 396 | // Define WalkUpFrom*() and empty Visit*() for all Type classes. |
| 397 | bool WalkUpFromType(Type *T) { return getDerived().VisitType(T); } |
| 398 | bool VisitType(Type *T) { return true; } |
| 399 | #define TYPE(CLASS, BASE) \ |
| 400 | bool WalkUpFrom##CLASS##Type(CLASS##Type *T) { \ |
| 401 | TRY_TO(WalkUpFrom##BASE(T)); \ |
| 402 | TRY_TO(Visit##CLASS##Type(T)); \ |
| 403 | return true; \ |
| 404 | } \ |
| 405 | bool Visit##CLASS##Type(CLASS##Type *T) { return true; } |
| 406 | #include "clang/AST/TypeNodes.inc" |
| 407 | |
| 408 | // ---- Methods on TypeLocs ---- |
| 409 | // FIXME: this currently just calls the matching Type methods |
| 410 | |
| 411 | // Declare Traverse*() for all concrete TypeLoc classes. |
| 412 | #define ABSTRACT_TYPELOC(CLASS, BASE) |
| 413 | #define TYPELOC(CLASS, BASE) bool Traverse##CLASS##TypeLoc(CLASS##TypeLoc TL); |
| 414 | #include "clang/AST/TypeLocNodes.def" |
| 415 | // The above header #undefs ABSTRACT_TYPELOC and TYPELOC upon exit. |
| 416 | |
| 417 | // Define WalkUpFrom*() and empty Visit*() for all TypeLoc classes. |
| 418 | bool WalkUpFromTypeLoc(TypeLoc TL) { return getDerived().VisitTypeLoc(TL); } |
| 419 | bool VisitTypeLoc(TypeLoc TL) { return true; } |
| 420 | |
| 421 | // QualifiedTypeLoc and UnqualTypeLoc are not declared in |
| 422 | // TypeNodes.inc and thus need to be handled specially. |
| 423 | bool WalkUpFromQualifiedTypeLoc(QualifiedTypeLoc TL) { |
| 424 | return getDerived().VisitUnqualTypeLoc(TL.getUnqualifiedLoc()); |
| 425 | } |
| 426 | bool VisitQualifiedTypeLoc(QualifiedTypeLoc TL) { return true; } |
| 427 | bool WalkUpFromUnqualTypeLoc(UnqualTypeLoc TL) { |
| 428 | return getDerived().VisitUnqualTypeLoc(TL.getUnqualifiedLoc()); |
| 429 | } |
| 430 | bool VisitUnqualTypeLoc(UnqualTypeLoc TL) { return true; } |
| 431 | |
| 432 | // Note that BASE includes trailing 'Type' which CLASS doesn't. |
| 433 | #define TYPE(CLASS, BASE) \ |
| 434 | bool WalkUpFrom##CLASS##TypeLoc(CLASS##TypeLoc TL) { \ |
| 435 | TRY_TO(WalkUpFrom##BASE##Loc(TL)); \ |
| 436 | TRY_TO(Visit##CLASS##TypeLoc(TL)); \ |
| 437 | return true; \ |
| 438 | } \ |
| 439 | bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TL) { return true; } |
| 440 | #include "clang/AST/TypeNodes.inc" |
| 441 | |
| 442 | // ---- Methods on Decls ---- |
| 443 | |
| 444 | // Declare Traverse*() for all concrete Decl classes. |
| 445 | #define ABSTRACT_DECL(DECL) |
| 446 | #define DECL(CLASS, BASE) bool Traverse##CLASS##Decl(CLASS##Decl *D); |
| 447 | #include "clang/AST/DeclNodes.inc" |
| 448 | // The above header #undefs ABSTRACT_DECL and DECL upon exit. |
| 449 | |
| 450 | // Define WalkUpFrom*() and empty Visit*() for all Decl classes. |
| 451 | bool WalkUpFromDecl(Decl *D) { return getDerived().VisitDecl(D); } |
| 452 | bool VisitDecl(Decl *D) { return true; } |
| 453 | #define DECL(CLASS, BASE) \ |
| 454 | bool WalkUpFrom##CLASS##Decl(CLASS##Decl *D) { \ |
| 455 | TRY_TO(WalkUpFrom##BASE(D)); \ |
| 456 | TRY_TO(Visit##CLASS##Decl(D)); \ |
| 457 | return true; \ |
| 458 | } \ |
| 459 | bool Visit##CLASS##Decl(CLASS##Decl *D) { return true; } |
| 460 | #include "clang/AST/DeclNodes.inc" |
| 461 | |
| 462 | bool canIgnoreChildDeclWhileTraversingDeclContext(const Decl *Child); |
| 463 | |
| 464 | #define DEF_TRAVERSE_TMPL_INST(TMPLDECLKIND) \ |
| 465 | bool TraverseTemplateInstantiations(TMPLDECLKIND##TemplateDecl *D); |
| 466 | DEF_TRAVERSE_TMPL_INST(Class) |
| 467 | DEF_TRAVERSE_TMPL_INST(Var) |
| 468 | DEF_TRAVERSE_TMPL_INST(Function) |
| 469 | #undef DEF_TRAVERSE_TMPL_INST |
| 470 | |
| 471 | bool TraverseTypeConstraint(const TypeConstraint *C); |
| 472 | |
| 473 | bool TraverseConceptRequirement(concepts::Requirement *R); |
| 474 | bool TraverseConceptTypeRequirement(concepts::TypeRequirement *R); |
| 475 | bool TraverseConceptExprRequirement(concepts::ExprRequirement *R); |
| 476 | bool TraverseConceptNestedRequirement(concepts::NestedRequirement *R); |
| 477 | |
| 478 | bool dataTraverseNode(Stmt *S, DataRecursionQueue *Queue); |
| 479 | |
| 480 | private: |
| 481 | // These are helper methods used by more than one Traverse* method. |
| 482 | bool TraverseTemplateParameterListHelper(TemplateParameterList *TPL); |
| 483 | |
| 484 | // Traverses template parameter lists of either a DeclaratorDecl or TagDecl. |
| 485 | template <typename T> |
| 486 | bool TraverseDeclTemplateParameterLists(T *D); |
| 487 | |
| 488 | bool TraverseTemplateTypeParamDeclConstraints(const TemplateTypeParmDecl *D); |
| 489 | |
| 490 | bool TraverseTemplateArgumentLocsHelper(const TemplateArgumentLoc *TAL, |
| 491 | unsigned Count); |
| 492 | bool TraverseArrayTypeLocHelper(ArrayTypeLoc TL); |
| 493 | bool TraverseRecordHelper(RecordDecl *D); |
| 494 | bool TraverseCXXRecordHelper(CXXRecordDecl *D); |
| 495 | bool TraverseDeclaratorHelper(DeclaratorDecl *D); |
| 496 | bool TraverseDeclContextHelper(DeclContext *DC); |
| 497 | bool TraverseFunctionHelper(FunctionDecl *D); |
| 498 | bool TraverseVarHelper(VarDecl *D); |
| 499 | bool TraverseOMPExecutableDirective(OMPExecutableDirective *S); |
| 500 | bool TraverseOMPLoopDirective(OMPLoopDirective *S); |
| 501 | bool TraverseOMPClause(OMPClause *C); |
| 502 | #define GEN_CLANG_CLAUSE_CLASS |
| 503 | #define CLAUSE_CLASS(Enum, Str, Class) bool Visit##Class(Class *C); |
| 504 | #include "llvm/Frontend/OpenMP/OMP.inc" |
| 505 | /// Process clauses with list of variables. |
| 506 | template <typename T> bool VisitOMPClauseList(T *Node); |
| 507 | /// Process clauses with pre-initis. |
| 508 | bool VisitOMPClauseWithPreInit(OMPClauseWithPreInit *Node); |
| 509 | bool VisitOMPClauseWithPostUpdate(OMPClauseWithPostUpdate *Node); |
| 510 | |
| 511 | bool PostVisitStmt(Stmt *S); |
| 512 | bool TraverseOpenACCConstructStmt(OpenACCConstructStmt *S); |
| 513 | bool |
| 514 | TraverseOpenACCAssociatedStmtConstruct(OpenACCAssociatedStmtConstruct *S); |
| 515 | bool VisitOpenACCClauseList(ArrayRef<const OpenACCClause *>); |
| 516 | bool VisitOpenACCClause(const OpenACCClause *); |
| 517 | }; |
| 518 | |
| 519 | template <typename Derived> |
| 520 | bool RecursiveASTVisitor<Derived>::TraverseTypeConstraint( |
| 521 | const TypeConstraint *C) { |
| 522 | if (!getDerived().shouldVisitImplicitCode()) { |
| 523 | TRY_TO(TraverseConceptReference(C->getConceptReference())); |
| 524 | return true; |
| 525 | } |
| 526 | if (Expr *IDC = C->getImmediatelyDeclaredConstraint()) { |
| 527 | TRY_TO(TraverseStmt(IDC)); |
| 528 | } else { |
| 529 | // Avoid traversing the ConceptReference in the TypeConstraint |
| 530 | // if we have an immediately-declared-constraint, otherwise |
| 531 | // we'll end up visiting the concept and the arguments in |
| 532 | // the TC twice. |
| 533 | TRY_TO(TraverseConceptReference(C->getConceptReference())); |
| 534 | } |
| 535 | return true; |
| 536 | } |
| 537 | |
| 538 | template <typename Derived> |
| 539 | bool RecursiveASTVisitor<Derived>::TraverseConceptRequirement( |
| 540 | concepts::Requirement *R) { |
| 541 | switch (R->getKind()) { |
| 542 | case concepts::Requirement::RK_Type: |
| 543 | return getDerived().TraverseConceptTypeRequirement( |
| 544 | cast<concepts::TypeRequirement>(Val: R)); |
| 545 | case concepts::Requirement::RK_Simple: |
| 546 | case concepts::Requirement::RK_Compound: |
| 547 | return getDerived().TraverseConceptExprRequirement( |
| 548 | cast<concepts::ExprRequirement>(Val: R)); |
| 549 | case concepts::Requirement::RK_Nested: |
| 550 | return getDerived().TraverseConceptNestedRequirement( |
| 551 | cast<concepts::NestedRequirement>(Val: R)); |
| 552 | } |
| 553 | llvm_unreachable("unexpected case" ); |
| 554 | } |
| 555 | |
| 556 | template <typename Derived> |
| 557 | bool RecursiveASTVisitor<Derived>::dataTraverseNode(Stmt *S, |
| 558 | DataRecursionQueue *Queue) { |
| 559 | // Top switch stmt: dispatch to TraverseFooStmt for each concrete FooStmt. |
| 560 | switch (S->getStmtClass()) { |
| 561 | case Stmt::NoStmtClass: |
| 562 | break; |
| 563 | #define ABSTRACT_STMT(STMT) |
| 564 | #define STMT(CLASS, PARENT) \ |
| 565 | case Stmt::CLASS##Class: \ |
| 566 | return TRAVERSE_STMT_BASE(CLASS, CLASS, S, Queue); |
| 567 | #include "clang/AST/StmtNodes.inc" |
| 568 | } |
| 569 | |
| 570 | return true; |
| 571 | } |
| 572 | |
| 573 | #undef DISPATCH_STMT |
| 574 | |
| 575 | template <typename Derived> |
| 576 | bool RecursiveASTVisitor<Derived>::TraverseConceptTypeRequirement( |
| 577 | concepts::TypeRequirement *R) { |
| 578 | if (R->isSubstitutionFailure()) |
| 579 | return true; |
| 580 | return getDerived().TraverseTypeLoc(R->getType()->getTypeLoc()); |
| 581 | } |
| 582 | |
| 583 | template <typename Derived> |
| 584 | bool RecursiveASTVisitor<Derived>::TraverseConceptExprRequirement( |
| 585 | concepts::ExprRequirement *R) { |
| 586 | if (!R->isExprSubstitutionFailure()) |
| 587 | TRY_TO(TraverseStmt(R->getExpr())); |
| 588 | auto &RetReq = R->getReturnTypeRequirement(); |
| 589 | if (RetReq.isTypeConstraint()) { |
| 590 | if (getDerived().shouldVisitImplicitCode()) { |
| 591 | TRY_TO(TraverseTemplateParameterListHelper( |
| 592 | RetReq.getTypeConstraintTemplateParameterList())); |
| 593 | } else { |
| 594 | // Template parameter list is implicit, visit constraint directly. |
| 595 | TRY_TO(TraverseTypeConstraint(RetReq.getTypeConstraint())); |
| 596 | } |
| 597 | } |
| 598 | return true; |
| 599 | } |
| 600 | |
| 601 | template <typename Derived> |
| 602 | bool RecursiveASTVisitor<Derived>::TraverseConceptNestedRequirement( |
| 603 | concepts::NestedRequirement *R) { |
| 604 | if (!R->hasInvalidConstraint()) |
| 605 | return getDerived().TraverseStmt(R->getConstraintExpr()); |
| 606 | return true; |
| 607 | } |
| 608 | |
| 609 | template <typename Derived> |
| 610 | bool RecursiveASTVisitor<Derived>::PostVisitStmt(Stmt *S) { |
| 611 | // In pre-order traversal mode, each Traverse##STMT method is responsible for |
| 612 | // calling WalkUpFrom. Therefore, if the user overrides Traverse##STMT and |
| 613 | // does not call the default implementation, the WalkUpFrom callback is not |
| 614 | // called. Post-order traversal mode should provide the same behavior |
| 615 | // regarding method overrides. |
| 616 | // |
| 617 | // In post-order traversal mode the Traverse##STMT method, when it receives a |
| 618 | // DataRecursionQueue, can't call WalkUpFrom after traversing children because |
| 619 | // it only enqueues the children and does not traverse them. TraverseStmt |
| 620 | // traverses the enqueued children, and we call WalkUpFrom here. |
| 621 | // |
| 622 | // However, to make pre-order and post-order modes identical with regards to |
| 623 | // whether they call WalkUpFrom at all, we call WalkUpFrom if and only if the |
| 624 | // user did not override the Traverse##STMT method. We implement the override |
| 625 | // check with isSameMethod calls below. |
| 626 | |
| 627 | switch (S->getStmtClass()) { |
| 628 | case Stmt::NoStmtClass: |
| 629 | break; |
| 630 | #define ABSTRACT_STMT(STMT) |
| 631 | #define STMT(CLASS, PARENT) \ |
| 632 | case Stmt::CLASS##Class: \ |
| 633 | if (::clang::detail::isSameMethod(&RecursiveASTVisitor::Traverse##CLASS, \ |
| 634 | &Derived::Traverse##CLASS)) { \ |
| 635 | TRY_TO(WalkUpFrom##CLASS(static_cast<CLASS *>(S))); \ |
| 636 | } \ |
| 637 | break; |
| 638 | #define INITLISTEXPR(CLASS, PARENT) \ |
| 639 | case Stmt::CLASS##Class: \ |
| 640 | if (::clang::detail::isSameMethod(&RecursiveASTVisitor::Traverse##CLASS, \ |
| 641 | &Derived::Traverse##CLASS)) { \ |
| 642 | auto ILE = static_cast<CLASS *>(S); \ |
| 643 | if (auto Syn = ILE->isSemanticForm() ? ILE->getSyntacticForm() : ILE) \ |
| 644 | TRY_TO(WalkUpFrom##CLASS(Syn)); \ |
| 645 | if (auto Sem = ILE->isSemanticForm() ? ILE : ILE->getSemanticForm()) \ |
| 646 | TRY_TO(WalkUpFrom##CLASS(Sem)); \ |
| 647 | } \ |
| 648 | break; |
| 649 | #include "clang/AST/StmtNodes.inc" |
| 650 | } |
| 651 | |
| 652 | return true; |
| 653 | } |
| 654 | |
| 655 | #undef DISPATCH_STMT |
| 656 | |
| 657 | // Inlining this method can lead to large code size and compile-time increases |
| 658 | // without any benefit to runtime performance. |
| 659 | template <typename Derived> |
| 660 | LLVM_ATTRIBUTE_NOINLINE bool |
| 661 | RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S, DataRecursionQueue *Queue) { |
| 662 | if (!S) |
| 663 | return true; |
| 664 | |
| 665 | if (Queue) { |
| 666 | Queue->push_back(Elt: {S, false}); |
| 667 | return true; |
| 668 | } |
| 669 | |
| 670 | SmallVector<llvm::PointerIntPair<Stmt *, 1, bool>, 8> LocalQueue; |
| 671 | LocalQueue.push_back(Elt: {S, false}); |
| 672 | |
| 673 | while (!LocalQueue.empty()) { |
| 674 | auto &CurrSAndVisited = LocalQueue.back(); |
| 675 | Stmt *CurrS = CurrSAndVisited.getPointer(); |
| 676 | bool Visited = CurrSAndVisited.getInt(); |
| 677 | if (Visited) { |
| 678 | LocalQueue.pop_back(); |
| 679 | TRY_TO(dataTraverseStmtPost(CurrS)); |
| 680 | if (getDerived().shouldTraversePostOrder()) { |
| 681 | TRY_TO(PostVisitStmt(CurrS)); |
| 682 | } |
| 683 | continue; |
| 684 | } |
| 685 | |
| 686 | if (getDerived().dataTraverseStmtPre(CurrS)) { |
| 687 | CurrSAndVisited.setInt(true); |
| 688 | size_t N = LocalQueue.size(); |
| 689 | TRY_TO(dataTraverseNode(CurrS, &LocalQueue)); |
| 690 | // Process new children in the order they were added. |
| 691 | std::reverse(first: LocalQueue.begin() + N, last: LocalQueue.end()); |
| 692 | } else { |
| 693 | LocalQueue.pop_back(); |
| 694 | } |
| 695 | } |
| 696 | |
| 697 | return true; |
| 698 | } |
| 699 | |
| 700 | template <typename Derived> |
| 701 | bool RecursiveASTVisitor<Derived>::TraverseType(QualType T) { |
| 702 | if (T.isNull()) |
| 703 | return true; |
| 704 | |
| 705 | switch (T->getTypeClass()) { |
| 706 | #define ABSTRACT_TYPE(CLASS, BASE) |
| 707 | #define TYPE(CLASS, BASE) \ |
| 708 | case Type::CLASS: \ |
| 709 | return getDerived().Traverse##CLASS##Type( \ |
| 710 | static_cast<CLASS##Type *>(const_cast<Type *>(T.getTypePtr()))); |
| 711 | #include "clang/AST/TypeNodes.inc" |
| 712 | } |
| 713 | |
| 714 | return true; |
| 715 | } |
| 716 | |
| 717 | template <typename Derived> |
| 718 | bool RecursiveASTVisitor<Derived>::TraverseTypeLoc(TypeLoc TL) { |
| 719 | if (TL.isNull()) |
| 720 | return true; |
| 721 | |
| 722 | switch (TL.getTypeLocClass()) { |
| 723 | #define ABSTRACT_TYPELOC(CLASS, BASE) |
| 724 | #define TYPELOC(CLASS, BASE) \ |
| 725 | case TypeLoc::CLASS: \ |
| 726 | return getDerived().Traverse##CLASS##TypeLoc(TL.castAs<CLASS##TypeLoc>()); |
| 727 | #include "clang/AST/TypeLocNodes.def" |
| 728 | } |
| 729 | |
| 730 | return true; |
| 731 | } |
| 732 | |
| 733 | // Define the Traverse*Attr(Attr* A) methods |
| 734 | #define VISITORCLASS RecursiveASTVisitor |
| 735 | #include "clang/AST/AttrVisitor.inc" |
| 736 | #undef VISITORCLASS |
| 737 | |
| 738 | template <typename Derived> |
| 739 | bool RecursiveASTVisitor<Derived>::TraverseDecl(Decl *D) { |
| 740 | if (!D) |
| 741 | return true; |
| 742 | |
| 743 | // As a syntax visitor, by default we want to ignore declarations for |
| 744 | // implicit declarations (ones not typed explicitly by the user). |
| 745 | if (!getDerived().shouldVisitImplicitCode()) { |
| 746 | if (D->isImplicit()) { |
| 747 | // For an implicit template type parameter, its type constraints are not |
| 748 | // implicit and are not represented anywhere else. We still need to visit |
| 749 | // them. |
| 750 | if (auto *TTPD = dyn_cast<TemplateTypeParmDecl>(Val: D)) |
| 751 | return TraverseTemplateTypeParamDeclConstraints(D: TTPD); |
| 752 | return true; |
| 753 | } |
| 754 | |
| 755 | // Deduction guides for alias templates are always synthesized, so they |
| 756 | // should not be traversed unless shouldVisitImplicitCode() returns true. |
| 757 | // |
| 758 | // It's important to note that checking the implicit bit is not efficient |
| 759 | // for the alias case. For deduction guides synthesized from explicit |
| 760 | // user-defined deduction guides, we must maintain the explicit bit to |
| 761 | // ensure correct overload resolution. |
| 762 | if (auto *FTD = dyn_cast<FunctionTemplateDecl>(Val: D)) |
| 763 | if (llvm::isa_and_present<TypeAliasTemplateDecl>( |
| 764 | Val: FTD->getDeclName().getCXXDeductionGuideTemplate())) |
| 765 | return true; |
| 766 | } |
| 767 | |
| 768 | switch (D->getKind()) { |
| 769 | #define ABSTRACT_DECL(DECL) |
| 770 | #define DECL(CLASS, BASE) \ |
| 771 | case Decl::CLASS: \ |
| 772 | if (!getDerived().Traverse##CLASS##Decl(static_cast<CLASS##Decl *>(D))) \ |
| 773 | return false; \ |
| 774 | break; |
| 775 | #include "clang/AST/DeclNodes.inc" |
| 776 | } |
| 777 | return true; |
| 778 | } |
| 779 | |
| 780 | template <typename Derived> |
| 781 | bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifier( |
| 782 | NestedNameSpecifier *NNS) { |
| 783 | if (!NNS) |
| 784 | return true; |
| 785 | |
| 786 | if (NNS->getPrefix()) |
| 787 | TRY_TO(TraverseNestedNameSpecifier(NNS->getPrefix())); |
| 788 | |
| 789 | switch (NNS->getKind()) { |
| 790 | case NestedNameSpecifier::Identifier: |
| 791 | case NestedNameSpecifier::Namespace: |
| 792 | case NestedNameSpecifier::NamespaceAlias: |
| 793 | case NestedNameSpecifier::Global: |
| 794 | case NestedNameSpecifier::Super: |
| 795 | return true; |
| 796 | |
| 797 | case NestedNameSpecifier::TypeSpec: |
| 798 | TRY_TO(TraverseType(QualType(NNS->getAsType(), 0))); |
| 799 | } |
| 800 | |
| 801 | return true; |
| 802 | } |
| 803 | |
| 804 | template <typename Derived> |
| 805 | bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifierLoc( |
| 806 | NestedNameSpecifierLoc NNS) { |
| 807 | if (!NNS) |
| 808 | return true; |
| 809 | |
| 810 | if (NestedNameSpecifierLoc Prefix = NNS.getPrefix()) |
| 811 | TRY_TO(TraverseNestedNameSpecifierLoc(Prefix)); |
| 812 | |
| 813 | switch (NNS.getNestedNameSpecifier()->getKind()) { |
| 814 | case NestedNameSpecifier::Identifier: |
| 815 | case NestedNameSpecifier::Namespace: |
| 816 | case NestedNameSpecifier::NamespaceAlias: |
| 817 | case NestedNameSpecifier::Global: |
| 818 | case NestedNameSpecifier::Super: |
| 819 | return true; |
| 820 | |
| 821 | case NestedNameSpecifier::TypeSpec: |
| 822 | TRY_TO(TraverseTypeLoc(NNS.getTypeLoc())); |
| 823 | break; |
| 824 | } |
| 825 | |
| 826 | return true; |
| 827 | } |
| 828 | |
| 829 | template <typename Derived> |
| 830 | bool RecursiveASTVisitor<Derived>::TraverseDeclarationNameInfo( |
| 831 | DeclarationNameInfo NameInfo) { |
| 832 | switch (NameInfo.getName().getNameKind()) { |
| 833 | case DeclarationName::CXXConstructorName: |
| 834 | case DeclarationName::CXXDestructorName: |
| 835 | case DeclarationName::CXXConversionFunctionName: |
| 836 | if (TypeSourceInfo *TSInfo = NameInfo.getNamedTypeInfo()) |
| 837 | TRY_TO(TraverseTypeLoc(TSInfo->getTypeLoc())); |
| 838 | break; |
| 839 | |
| 840 | case DeclarationName::CXXDeductionGuideName: |
| 841 | TRY_TO(TraverseTemplateName( |
| 842 | TemplateName(NameInfo.getName().getCXXDeductionGuideTemplate()))); |
| 843 | break; |
| 844 | |
| 845 | case DeclarationName::Identifier: |
| 846 | case DeclarationName::ObjCZeroArgSelector: |
| 847 | case DeclarationName::ObjCOneArgSelector: |
| 848 | case DeclarationName::ObjCMultiArgSelector: |
| 849 | case DeclarationName::CXXOperatorName: |
| 850 | case DeclarationName::CXXLiteralOperatorName: |
| 851 | case DeclarationName::CXXUsingDirective: |
| 852 | break; |
| 853 | } |
| 854 | |
| 855 | return true; |
| 856 | } |
| 857 | |
| 858 | template <typename Derived> |
| 859 | bool RecursiveASTVisitor<Derived>::TraverseTemplateName(TemplateName Template) { |
| 860 | if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) { |
| 861 | TRY_TO(TraverseNestedNameSpecifier(DTN->getQualifier())); |
| 862 | } else if (QualifiedTemplateName *QTN = |
| 863 | Template.getAsQualifiedTemplateName()) { |
| 864 | if (QTN->getQualifier()) { |
| 865 | TRY_TO(TraverseNestedNameSpecifier(QTN->getQualifier())); |
| 866 | } |
| 867 | } |
| 868 | |
| 869 | return true; |
| 870 | } |
| 871 | |
| 872 | template <typename Derived> |
| 873 | bool RecursiveASTVisitor<Derived>::TraverseTemplateArgument( |
| 874 | const TemplateArgument &Arg) { |
| 875 | switch (Arg.getKind()) { |
| 876 | case TemplateArgument::Null: |
| 877 | case TemplateArgument::Declaration: |
| 878 | case TemplateArgument::Integral: |
| 879 | case TemplateArgument::NullPtr: |
| 880 | case TemplateArgument::StructuralValue: |
| 881 | return true; |
| 882 | |
| 883 | case TemplateArgument::Type: |
| 884 | return getDerived().TraverseType(Arg.getAsType()); |
| 885 | |
| 886 | case TemplateArgument::Template: |
| 887 | case TemplateArgument::TemplateExpansion: |
| 888 | return getDerived().TraverseTemplateName( |
| 889 | Arg.getAsTemplateOrTemplatePattern()); |
| 890 | |
| 891 | case TemplateArgument::Expression: |
| 892 | return getDerived().TraverseStmt(Arg.getAsExpr()); |
| 893 | |
| 894 | case TemplateArgument::Pack: |
| 895 | return getDerived().TraverseTemplateArguments(Arg.pack_elements()); |
| 896 | } |
| 897 | |
| 898 | return true; |
| 899 | } |
| 900 | |
| 901 | // FIXME: no template name location? |
| 902 | // FIXME: no source locations for a template argument pack? |
| 903 | template <typename Derived> |
| 904 | bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLoc( |
| 905 | const TemplateArgumentLoc &ArgLoc) { |
| 906 | const TemplateArgument &Arg = ArgLoc.getArgument(); |
| 907 | |
| 908 | switch (Arg.getKind()) { |
| 909 | case TemplateArgument::Null: |
| 910 | case TemplateArgument::Declaration: |
| 911 | case TemplateArgument::Integral: |
| 912 | case TemplateArgument::NullPtr: |
| 913 | case TemplateArgument::StructuralValue: |
| 914 | return true; |
| 915 | |
| 916 | case TemplateArgument::Type: { |
| 917 | // FIXME: how can TSI ever be NULL? |
| 918 | if (TypeSourceInfo *TSI = ArgLoc.getTypeSourceInfo()) |
| 919 | return getDerived().TraverseTypeLoc(TSI->getTypeLoc()); |
| 920 | else |
| 921 | return getDerived().TraverseType(Arg.getAsType()); |
| 922 | } |
| 923 | |
| 924 | case TemplateArgument::Template: |
| 925 | case TemplateArgument::TemplateExpansion: |
| 926 | if (ArgLoc.getTemplateQualifierLoc()) |
| 927 | TRY_TO(getDerived().TraverseNestedNameSpecifierLoc( |
| 928 | ArgLoc.getTemplateQualifierLoc())); |
| 929 | return getDerived().TraverseTemplateName( |
| 930 | Arg.getAsTemplateOrTemplatePattern()); |
| 931 | |
| 932 | case TemplateArgument::Expression: |
| 933 | return getDerived().TraverseStmt(ArgLoc.getSourceExpression()); |
| 934 | |
| 935 | case TemplateArgument::Pack: |
| 936 | return getDerived().TraverseTemplateArguments(Arg.pack_elements()); |
| 937 | } |
| 938 | |
| 939 | return true; |
| 940 | } |
| 941 | |
| 942 | template <typename Derived> |
| 943 | bool RecursiveASTVisitor<Derived>::TraverseTemplateArguments( |
| 944 | ArrayRef<TemplateArgument> Args) { |
| 945 | for (const TemplateArgument &Arg : Args) |
| 946 | TRY_TO(TraverseTemplateArgument(Arg)); |
| 947 | |
| 948 | return true; |
| 949 | } |
| 950 | |
| 951 | template <typename Derived> |
| 952 | bool RecursiveASTVisitor<Derived>::TraverseConstructorInitializer( |
| 953 | CXXCtorInitializer *Init) { |
| 954 | if (TypeSourceInfo *TInfo = Init->getTypeSourceInfo()) |
| 955 | TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc())); |
| 956 | |
| 957 | if (Init->isWritten() || getDerived().shouldVisitImplicitCode()) |
| 958 | TRY_TO(TraverseStmt(Init->getInit())); |
| 959 | |
| 960 | return true; |
| 961 | } |
| 962 | |
| 963 | template <typename Derived> |
| 964 | bool |
| 965 | RecursiveASTVisitor<Derived>::TraverseLambdaCapture(LambdaExpr *LE, |
| 966 | const LambdaCapture *C, |
| 967 | Expr *Init) { |
| 968 | if (LE->isInitCapture(Capture: C)) |
| 969 | TRY_TO(TraverseDecl(C->getCapturedVar())); |
| 970 | else |
| 971 | TRY_TO(TraverseStmt(Init)); |
| 972 | return true; |
| 973 | } |
| 974 | |
| 975 | // ----------------- Type traversal ----------------- |
| 976 | |
| 977 | // This macro makes available a variable T, the passed-in type. |
| 978 | #define DEF_TRAVERSE_TYPE(TYPE, CODE) \ |
| 979 | template <typename Derived> \ |
| 980 | bool RecursiveASTVisitor<Derived>::Traverse##TYPE(TYPE *T) { \ |
| 981 | if (!getDerived().shouldTraversePostOrder()) \ |
| 982 | TRY_TO(WalkUpFrom##TYPE(T)); \ |
| 983 | { CODE; } \ |
| 984 | if (getDerived().shouldTraversePostOrder()) \ |
| 985 | TRY_TO(WalkUpFrom##TYPE(T)); \ |
| 986 | return true; \ |
| 987 | } |
| 988 | |
| 989 | DEF_TRAVERSE_TYPE(BuiltinType, {}) |
| 990 | |
| 991 | DEF_TRAVERSE_TYPE(ComplexType, { TRY_TO(TraverseType(T->getElementType())); }) |
| 992 | |
| 993 | DEF_TRAVERSE_TYPE(PointerType, { TRY_TO(TraverseType(T->getPointeeType())); }) |
| 994 | |
| 995 | DEF_TRAVERSE_TYPE(BlockPointerType, |
| 996 | { TRY_TO(TraverseType(T->getPointeeType())); }) |
| 997 | |
| 998 | DEF_TRAVERSE_TYPE(LValueReferenceType, |
| 999 | { TRY_TO(TraverseType(T->getPointeeType())); }) |
| 1000 | |
| 1001 | DEF_TRAVERSE_TYPE(RValueReferenceType, |
| 1002 | { TRY_TO(TraverseType(T->getPointeeType())); }) |
| 1003 | |
| 1004 | DEF_TRAVERSE_TYPE(MemberPointerType, { |
| 1005 | TRY_TO(TraverseNestedNameSpecifier(T->getQualifier())); |
| 1006 | if (T->isSugared()) |
| 1007 | TRY_TO(TraverseType( |
| 1008 | QualType(T->getMostRecentCXXRecordDecl()->getTypeForDecl(), 0))); |
| 1009 | TRY_TO(TraverseType(T->getPointeeType())); |
| 1010 | }) |
| 1011 | |
| 1012 | DEF_TRAVERSE_TYPE(AdjustedType, { TRY_TO(TraverseType(T->getOriginalType())); }) |
| 1013 | |
| 1014 | DEF_TRAVERSE_TYPE(DecayedType, { TRY_TO(TraverseType(T->getOriginalType())); }) |
| 1015 | |
| 1016 | DEF_TRAVERSE_TYPE(ConstantArrayType, { |
| 1017 | TRY_TO(TraverseType(T->getElementType())); |
| 1018 | if (T->getSizeExpr()) |
| 1019 | TRY_TO(TraverseStmt(const_cast<Expr*>(T->getSizeExpr()))); |
| 1020 | }) |
| 1021 | |
| 1022 | DEF_TRAVERSE_TYPE(ArrayParameterType, { |
| 1023 | TRY_TO(TraverseType(T->getElementType())); |
| 1024 | if (T->getSizeExpr()) |
| 1025 | TRY_TO(TraverseStmt(const_cast<Expr *>(T->getSizeExpr()))); |
| 1026 | }) |
| 1027 | |
| 1028 | DEF_TRAVERSE_TYPE(IncompleteArrayType, |
| 1029 | { TRY_TO(TraverseType(T->getElementType())); }) |
| 1030 | |
| 1031 | DEF_TRAVERSE_TYPE(VariableArrayType, { |
| 1032 | TRY_TO(TraverseType(T->getElementType())); |
| 1033 | TRY_TO(TraverseStmt(T->getSizeExpr())); |
| 1034 | }) |
| 1035 | |
| 1036 | DEF_TRAVERSE_TYPE(DependentSizedArrayType, { |
| 1037 | TRY_TO(TraverseType(T->getElementType())); |
| 1038 | if (T->getSizeExpr()) |
| 1039 | TRY_TO(TraverseStmt(T->getSizeExpr())); |
| 1040 | }) |
| 1041 | |
| 1042 | DEF_TRAVERSE_TYPE(DependentAddressSpaceType, { |
| 1043 | TRY_TO(TraverseStmt(T->getAddrSpaceExpr())); |
| 1044 | TRY_TO(TraverseType(T->getPointeeType())); |
| 1045 | }) |
| 1046 | |
| 1047 | DEF_TRAVERSE_TYPE(DependentVectorType, { |
| 1048 | if (T->getSizeExpr()) |
| 1049 | TRY_TO(TraverseStmt(T->getSizeExpr())); |
| 1050 | TRY_TO(TraverseType(T->getElementType())); |
| 1051 | }) |
| 1052 | |
| 1053 | DEF_TRAVERSE_TYPE(DependentSizedExtVectorType, { |
| 1054 | if (T->getSizeExpr()) |
| 1055 | TRY_TO(TraverseStmt(T->getSizeExpr())); |
| 1056 | TRY_TO(TraverseType(T->getElementType())); |
| 1057 | }) |
| 1058 | |
| 1059 | DEF_TRAVERSE_TYPE(VectorType, { TRY_TO(TraverseType(T->getElementType())); }) |
| 1060 | |
| 1061 | DEF_TRAVERSE_TYPE(ExtVectorType, { TRY_TO(TraverseType(T->getElementType())); }) |
| 1062 | |
| 1063 | DEF_TRAVERSE_TYPE(ConstantMatrixType, |
| 1064 | { TRY_TO(TraverseType(T->getElementType())); }) |
| 1065 | |
| 1066 | DEF_TRAVERSE_TYPE(DependentSizedMatrixType, { |
| 1067 | if (T->getRowExpr()) |
| 1068 | TRY_TO(TraverseStmt(T->getRowExpr())); |
| 1069 | if (T->getColumnExpr()) |
| 1070 | TRY_TO(TraverseStmt(T->getColumnExpr())); |
| 1071 | TRY_TO(TraverseType(T->getElementType())); |
| 1072 | }) |
| 1073 | |
| 1074 | DEF_TRAVERSE_TYPE(FunctionNoProtoType, |
| 1075 | { TRY_TO(TraverseType(T->getReturnType())); }) |
| 1076 | |
| 1077 | DEF_TRAVERSE_TYPE(FunctionProtoType, { |
| 1078 | TRY_TO(TraverseType(T->getReturnType())); |
| 1079 | |
| 1080 | for (const auto &A : T->param_types()) { |
| 1081 | TRY_TO(TraverseType(A)); |
| 1082 | } |
| 1083 | |
| 1084 | for (const auto &E : T->exceptions()) { |
| 1085 | TRY_TO(TraverseType(E)); |
| 1086 | } |
| 1087 | |
| 1088 | if (Expr *NE = T->getNoexceptExpr()) |
| 1089 | TRY_TO(TraverseStmt(NE)); |
| 1090 | }) |
| 1091 | |
| 1092 | DEF_TRAVERSE_TYPE(UsingType, {}) |
| 1093 | DEF_TRAVERSE_TYPE(UnresolvedUsingType, {}) |
| 1094 | DEF_TRAVERSE_TYPE(TypedefType, {}) |
| 1095 | |
| 1096 | DEF_TRAVERSE_TYPE(TypeOfExprType, |
| 1097 | { TRY_TO(TraverseStmt(T->getUnderlyingExpr())); }) |
| 1098 | |
| 1099 | DEF_TRAVERSE_TYPE(TypeOfType, { TRY_TO(TraverseType(T->getUnmodifiedType())); }) |
| 1100 | |
| 1101 | DEF_TRAVERSE_TYPE(DecltypeType, |
| 1102 | { TRY_TO(TraverseStmt(T->getUnderlyingExpr())); }) |
| 1103 | |
| 1104 | DEF_TRAVERSE_TYPE(PackIndexingType, { |
| 1105 | TRY_TO(TraverseType(T->getPattern())); |
| 1106 | TRY_TO(TraverseStmt(T->getIndexExpr())); |
| 1107 | }) |
| 1108 | |
| 1109 | DEF_TRAVERSE_TYPE(UnaryTransformType, { |
| 1110 | TRY_TO(TraverseType(T->getBaseType())); |
| 1111 | TRY_TO(TraverseType(T->getUnderlyingType())); |
| 1112 | }) |
| 1113 | |
| 1114 | DEF_TRAVERSE_TYPE(AutoType, { |
| 1115 | TRY_TO(TraverseType(T->getDeducedType())); |
| 1116 | if (T->isConstrained()) { |
| 1117 | TRY_TO(TraverseTemplateArguments(T->getTypeConstraintArguments())); |
| 1118 | } |
| 1119 | }) |
| 1120 | DEF_TRAVERSE_TYPE(DeducedTemplateSpecializationType, { |
| 1121 | TRY_TO(TraverseTemplateName(T->getTemplateName())); |
| 1122 | TRY_TO(TraverseType(T->getDeducedType())); |
| 1123 | }) |
| 1124 | |
| 1125 | DEF_TRAVERSE_TYPE(RecordType, {}) |
| 1126 | DEF_TRAVERSE_TYPE(EnumType, {}) |
| 1127 | DEF_TRAVERSE_TYPE(TemplateTypeParmType, {}) |
| 1128 | DEF_TRAVERSE_TYPE(SubstTemplateTypeParmType, { |
| 1129 | TRY_TO(TraverseType(T->getReplacementType())); |
| 1130 | }) |
| 1131 | DEF_TRAVERSE_TYPE(SubstTemplateTypeParmPackType, { |
| 1132 | TRY_TO(TraverseTemplateArgument(T->getArgumentPack())); |
| 1133 | }) |
| 1134 | |
| 1135 | DEF_TRAVERSE_TYPE(TemplateSpecializationType, { |
| 1136 | TRY_TO(TraverseTemplateName(T->getTemplateName())); |
| 1137 | TRY_TO(TraverseTemplateArguments(T->template_arguments())); |
| 1138 | }) |
| 1139 | |
| 1140 | DEF_TRAVERSE_TYPE(InjectedClassNameType, {}) |
| 1141 | |
| 1142 | DEF_TRAVERSE_TYPE(AttributedType, |
| 1143 | { TRY_TO(TraverseType(T->getModifiedType())); }) |
| 1144 | |
| 1145 | DEF_TRAVERSE_TYPE(CountAttributedType, { |
| 1146 | if (T->getCountExpr()) |
| 1147 | TRY_TO(TraverseStmt(T->getCountExpr())); |
| 1148 | TRY_TO(TraverseType(T->desugar())); |
| 1149 | }) |
| 1150 | |
| 1151 | DEF_TRAVERSE_TYPE(BTFTagAttributedType, |
| 1152 | { TRY_TO(TraverseType(T->getWrappedType())); }) |
| 1153 | |
| 1154 | DEF_TRAVERSE_TYPE(HLSLAttributedResourceType, |
| 1155 | { TRY_TO(TraverseType(T->getWrappedType())); }) |
| 1156 | |
| 1157 | DEF_TRAVERSE_TYPE(HLSLInlineSpirvType, { |
| 1158 | for (auto &Operand : T->getOperands()) { |
| 1159 | if (Operand.isConstant() || Operand.isType()) { |
| 1160 | TRY_TO(TraverseType(Operand.getResultType())); |
| 1161 | } |
| 1162 | } |
| 1163 | }) |
| 1164 | |
| 1165 | DEF_TRAVERSE_TYPE(ParenType, { TRY_TO(TraverseType(T->getInnerType())); }) |
| 1166 | |
| 1167 | DEF_TRAVERSE_TYPE(MacroQualifiedType, |
| 1168 | { TRY_TO(TraverseType(T->getUnderlyingType())); }) |
| 1169 | |
| 1170 | DEF_TRAVERSE_TYPE(ElaboratedType, { |
| 1171 | if (T->getQualifier()) { |
| 1172 | TRY_TO(TraverseNestedNameSpecifier(T->getQualifier())); |
| 1173 | } |
| 1174 | TRY_TO(TraverseType(T->getNamedType())); |
| 1175 | }) |
| 1176 | |
| 1177 | DEF_TRAVERSE_TYPE(DependentNameType, |
| 1178 | { TRY_TO(TraverseNestedNameSpecifier(T->getQualifier())); }) |
| 1179 | |
| 1180 | DEF_TRAVERSE_TYPE(DependentTemplateSpecializationType, { |
| 1181 | const DependentTemplateStorage &S = T->getDependentTemplateName(); |
| 1182 | TRY_TO(TraverseNestedNameSpecifier(S.getQualifier())); |
| 1183 | TRY_TO(TraverseTemplateArguments(T->template_arguments())); |
| 1184 | }) |
| 1185 | |
| 1186 | DEF_TRAVERSE_TYPE(PackExpansionType, { TRY_TO(TraverseType(T->getPattern())); }) |
| 1187 | |
| 1188 | DEF_TRAVERSE_TYPE(ObjCTypeParamType, {}) |
| 1189 | |
| 1190 | DEF_TRAVERSE_TYPE(ObjCInterfaceType, {}) |
| 1191 | |
| 1192 | DEF_TRAVERSE_TYPE(ObjCObjectType, { |
| 1193 | // We have to watch out here because an ObjCInterfaceType's base |
| 1194 | // type is itself. |
| 1195 | if (T->getBaseType().getTypePtr() != T) |
| 1196 | TRY_TO(TraverseType(T->getBaseType())); |
| 1197 | for (auto typeArg : T->getTypeArgsAsWritten()) { |
| 1198 | TRY_TO(TraverseType(typeArg)); |
| 1199 | } |
| 1200 | }) |
| 1201 | |
| 1202 | DEF_TRAVERSE_TYPE(ObjCObjectPointerType, |
| 1203 | { TRY_TO(TraverseType(T->getPointeeType())); }) |
| 1204 | |
| 1205 | DEF_TRAVERSE_TYPE(AtomicType, { TRY_TO(TraverseType(T->getValueType())); }) |
| 1206 | |
| 1207 | DEF_TRAVERSE_TYPE(PipeType, { TRY_TO(TraverseType(T->getElementType())); }) |
| 1208 | |
| 1209 | DEF_TRAVERSE_TYPE(BitIntType, {}) |
| 1210 | DEF_TRAVERSE_TYPE(DependentBitIntType, |
| 1211 | { TRY_TO(TraverseStmt(T->getNumBitsExpr())); }) |
| 1212 | |
| 1213 | #undef DEF_TRAVERSE_TYPE |
| 1214 | |
| 1215 | // ----------------- TypeLoc traversal ----------------- |
| 1216 | |
| 1217 | // This macro makes available a variable TL, the passed-in TypeLoc. |
| 1218 | // If requested, it calls WalkUpFrom* for the Type in the given TypeLoc, |
| 1219 | // in addition to WalkUpFrom* for the TypeLoc itself, such that existing |
| 1220 | // clients that override the WalkUpFrom*Type() and/or Visit*Type() methods |
| 1221 | // continue to work. |
| 1222 | #define DEF_TRAVERSE_TYPELOC(TYPE, CODE) \ |
| 1223 | template <typename Derived> \ |
| 1224 | bool RecursiveASTVisitor<Derived>::Traverse##TYPE##Loc(TYPE##Loc TL) { \ |
| 1225 | if (!getDerived().shouldTraversePostOrder()) { \ |
| 1226 | TRY_TO(WalkUpFrom##TYPE##Loc(TL)); \ |
| 1227 | if (getDerived().shouldWalkTypesOfTypeLocs()) \ |
| 1228 | TRY_TO(WalkUpFrom##TYPE(const_cast<TYPE *>(TL.getTypePtr()))); \ |
| 1229 | } \ |
| 1230 | { CODE; } \ |
| 1231 | if (getDerived().shouldTraversePostOrder()) { \ |
| 1232 | TRY_TO(WalkUpFrom##TYPE##Loc(TL)); \ |
| 1233 | if (getDerived().shouldWalkTypesOfTypeLocs()) \ |
| 1234 | TRY_TO(WalkUpFrom##TYPE(const_cast<TYPE *>(TL.getTypePtr()))); \ |
| 1235 | } \ |
| 1236 | return true; \ |
| 1237 | } |
| 1238 | |
| 1239 | template <typename Derived> |
| 1240 | bool |
| 1241 | RecursiveASTVisitor<Derived>::TraverseQualifiedTypeLoc(QualifiedTypeLoc TL) { |
| 1242 | // Move this over to the 'main' typeloc tree. Note that this is a |
| 1243 | // move -- we pretend that we were really looking at the unqualified |
| 1244 | // typeloc all along -- rather than a recursion, so we don't follow |
| 1245 | // the normal CRTP plan of going through |
| 1246 | // getDerived().TraverseTypeLoc. If we did, we'd be traversing |
| 1247 | // twice for the same type (once as a QualifiedTypeLoc version of |
| 1248 | // the type, once as an UnqualifiedTypeLoc version of the type), |
| 1249 | // which in effect means we'd call VisitTypeLoc twice with the |
| 1250 | // 'same' type. This solves that problem, at the cost of never |
| 1251 | // seeing the qualified version of the type (unless the client |
| 1252 | // subclasses TraverseQualifiedTypeLoc themselves). It's not a |
| 1253 | // perfect solution. A perfect solution probably requires making |
| 1254 | // QualifiedTypeLoc a wrapper around TypeLoc -- like QualType is a |
| 1255 | // wrapper around Type* -- rather than being its own class in the |
| 1256 | // type hierarchy. |
| 1257 | return TraverseTypeLoc(TL: TL.getUnqualifiedLoc()); |
| 1258 | } |
| 1259 | |
| 1260 | DEF_TRAVERSE_TYPELOC(BuiltinType, {}) |
| 1261 | |
| 1262 | // FIXME: ComplexTypeLoc is unfinished |
| 1263 | DEF_TRAVERSE_TYPELOC(ComplexType, { |
| 1264 | TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); |
| 1265 | }) |
| 1266 | |
| 1267 | DEF_TRAVERSE_TYPELOC(PointerType, |
| 1268 | { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); }) |
| 1269 | |
| 1270 | DEF_TRAVERSE_TYPELOC(BlockPointerType, |
| 1271 | { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); }) |
| 1272 | |
| 1273 | DEF_TRAVERSE_TYPELOC(LValueReferenceType, |
| 1274 | { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); }) |
| 1275 | |
| 1276 | DEF_TRAVERSE_TYPELOC(RValueReferenceType, |
| 1277 | { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); }) |
| 1278 | |
| 1279 | // We traverse this in the type case as well, but how is it not reached through |
| 1280 | // the pointee type? |
| 1281 | DEF_TRAVERSE_TYPELOC(MemberPointerType, { |
| 1282 | if (NestedNameSpecifierLoc QL = TL.getQualifierLoc()) |
| 1283 | TRY_TO(TraverseNestedNameSpecifierLoc(QL)); |
| 1284 | else |
| 1285 | TRY_TO(TraverseNestedNameSpecifier(TL.getTypePtr()->getQualifier())); |
| 1286 | TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); |
| 1287 | }) |
| 1288 | |
| 1289 | DEF_TRAVERSE_TYPELOC(AdjustedType, |
| 1290 | { TRY_TO(TraverseTypeLoc(TL.getOriginalLoc())); }) |
| 1291 | |
| 1292 | DEF_TRAVERSE_TYPELOC(DecayedType, |
| 1293 | { TRY_TO(TraverseTypeLoc(TL.getOriginalLoc())); }) |
| 1294 | |
| 1295 | template <typename Derived> |
| 1296 | bool RecursiveASTVisitor<Derived>::TraverseArrayTypeLocHelper(ArrayTypeLoc TL) { |
| 1297 | // This isn't available for ArrayType, but is for the ArrayTypeLoc. |
| 1298 | TRY_TO(TraverseStmt(TL.getSizeExpr())); |
| 1299 | return true; |
| 1300 | } |
| 1301 | |
| 1302 | DEF_TRAVERSE_TYPELOC(ConstantArrayType, { |
| 1303 | TRY_TO(TraverseTypeLoc(TL.getElementLoc())); |
| 1304 | TRY_TO(TraverseArrayTypeLocHelper(TL)); |
| 1305 | }) |
| 1306 | |
| 1307 | DEF_TRAVERSE_TYPELOC(ArrayParameterType, { |
| 1308 | TRY_TO(TraverseTypeLoc(TL.getElementLoc())); |
| 1309 | TRY_TO(TraverseArrayTypeLocHelper(TL)); |
| 1310 | }) |
| 1311 | |
| 1312 | DEF_TRAVERSE_TYPELOC(IncompleteArrayType, { |
| 1313 | TRY_TO(TraverseTypeLoc(TL.getElementLoc())); |
| 1314 | TRY_TO(TraverseArrayTypeLocHelper(TL)); |
| 1315 | }) |
| 1316 | |
| 1317 | DEF_TRAVERSE_TYPELOC(VariableArrayType, { |
| 1318 | TRY_TO(TraverseTypeLoc(TL.getElementLoc())); |
| 1319 | TRY_TO(TraverseArrayTypeLocHelper(TL)); |
| 1320 | }) |
| 1321 | |
| 1322 | DEF_TRAVERSE_TYPELOC(DependentSizedArrayType, { |
| 1323 | TRY_TO(TraverseTypeLoc(TL.getElementLoc())); |
| 1324 | TRY_TO(TraverseArrayTypeLocHelper(TL)); |
| 1325 | }) |
| 1326 | |
| 1327 | DEF_TRAVERSE_TYPELOC(DependentAddressSpaceType, { |
| 1328 | TRY_TO(TraverseStmt(TL.getTypePtr()->getAddrSpaceExpr())); |
| 1329 | TRY_TO(TraverseType(TL.getTypePtr()->getPointeeType())); |
| 1330 | }) |
| 1331 | |
| 1332 | // FIXME: order? why not size expr first? |
| 1333 | // FIXME: base VectorTypeLoc is unfinished |
| 1334 | DEF_TRAVERSE_TYPELOC(DependentSizedExtVectorType, { |
| 1335 | if (TL.getTypePtr()->getSizeExpr()) |
| 1336 | TRY_TO(TraverseStmt(TL.getTypePtr()->getSizeExpr())); |
| 1337 | TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); |
| 1338 | }) |
| 1339 | |
| 1340 | // FIXME: VectorTypeLoc is unfinished |
| 1341 | DEF_TRAVERSE_TYPELOC(VectorType, { |
| 1342 | TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); |
| 1343 | }) |
| 1344 | |
| 1345 | DEF_TRAVERSE_TYPELOC(DependentVectorType, { |
| 1346 | if (TL.getTypePtr()->getSizeExpr()) |
| 1347 | TRY_TO(TraverseStmt(TL.getTypePtr()->getSizeExpr())); |
| 1348 | TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); |
| 1349 | }) |
| 1350 | |
| 1351 | // FIXME: size and attributes |
| 1352 | // FIXME: base VectorTypeLoc is unfinished |
| 1353 | DEF_TRAVERSE_TYPELOC(ExtVectorType, { |
| 1354 | TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); |
| 1355 | }) |
| 1356 | |
| 1357 | DEF_TRAVERSE_TYPELOC(ConstantMatrixType, { |
| 1358 | TRY_TO(TraverseStmt(TL.getAttrRowOperand())); |
| 1359 | TRY_TO(TraverseStmt(TL.getAttrColumnOperand())); |
| 1360 | TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); |
| 1361 | }) |
| 1362 | |
| 1363 | DEF_TRAVERSE_TYPELOC(DependentSizedMatrixType, { |
| 1364 | TRY_TO(TraverseStmt(TL.getAttrRowOperand())); |
| 1365 | TRY_TO(TraverseStmt(TL.getAttrColumnOperand())); |
| 1366 | TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); |
| 1367 | }) |
| 1368 | |
| 1369 | DEF_TRAVERSE_TYPELOC(FunctionNoProtoType, |
| 1370 | { TRY_TO(TraverseTypeLoc(TL.getReturnLoc())); }) |
| 1371 | |
| 1372 | // FIXME: location of exception specifications (attributes?) |
| 1373 | DEF_TRAVERSE_TYPELOC(FunctionProtoType, { |
| 1374 | TRY_TO(TraverseTypeLoc(TL.getReturnLoc())); |
| 1375 | |
| 1376 | const FunctionProtoType *T = TL.getTypePtr(); |
| 1377 | |
| 1378 | for (unsigned I = 0, E = TL.getNumParams(); I != E; ++I) { |
| 1379 | if (TL.getParam(I)) { |
| 1380 | TRY_TO(TraverseDecl(TL.getParam(I))); |
| 1381 | } else if (I < T->getNumParams()) { |
| 1382 | TRY_TO(TraverseType(T->getParamType(I))); |
| 1383 | } |
| 1384 | } |
| 1385 | |
| 1386 | for (const auto &E : T->exceptions()) { |
| 1387 | TRY_TO(TraverseType(E)); |
| 1388 | } |
| 1389 | |
| 1390 | if (Expr *NE = T->getNoexceptExpr()) |
| 1391 | TRY_TO(TraverseStmt(NE)); |
| 1392 | }) |
| 1393 | |
| 1394 | DEF_TRAVERSE_TYPELOC(UsingType, {}) |
| 1395 | DEF_TRAVERSE_TYPELOC(UnresolvedUsingType, {}) |
| 1396 | DEF_TRAVERSE_TYPELOC(TypedefType, {}) |
| 1397 | |
| 1398 | DEF_TRAVERSE_TYPELOC(TypeOfExprType, |
| 1399 | { TRY_TO(TraverseStmt(TL.getUnderlyingExpr())); }) |
| 1400 | |
| 1401 | DEF_TRAVERSE_TYPELOC(TypeOfType, { |
| 1402 | TRY_TO(TraverseTypeLoc(TL.getUnmodifiedTInfo()->getTypeLoc())); |
| 1403 | }) |
| 1404 | |
| 1405 | // FIXME: location of underlying expr |
| 1406 | DEF_TRAVERSE_TYPELOC(DecltypeType, { |
| 1407 | TRY_TO(TraverseStmt(TL.getTypePtr()->getUnderlyingExpr())); |
| 1408 | }) |
| 1409 | |
| 1410 | DEF_TRAVERSE_TYPELOC(PackIndexingType, { |
| 1411 | TRY_TO(TraverseType(TL.getPattern())); |
| 1412 | TRY_TO(TraverseStmt(TL.getTypePtr()->getIndexExpr())); |
| 1413 | }) |
| 1414 | |
| 1415 | DEF_TRAVERSE_TYPELOC(UnaryTransformType, { |
| 1416 | TRY_TO(TraverseTypeLoc(TL.getUnderlyingTInfo()->getTypeLoc())); |
| 1417 | }) |
| 1418 | |
| 1419 | DEF_TRAVERSE_TYPELOC(AutoType, { |
| 1420 | TRY_TO(TraverseType(TL.getTypePtr()->getDeducedType())); |
| 1421 | if (TL.isConstrained()) { |
| 1422 | TRY_TO(TraverseConceptReference(TL.getConceptReference())); |
| 1423 | } |
| 1424 | }) |
| 1425 | |
| 1426 | DEF_TRAVERSE_TYPELOC(DeducedTemplateSpecializationType, { |
| 1427 | TRY_TO(TraverseTemplateName(TL.getTypePtr()->getTemplateName())); |
| 1428 | TRY_TO(TraverseType(TL.getTypePtr()->getDeducedType())); |
| 1429 | }) |
| 1430 | |
| 1431 | DEF_TRAVERSE_TYPELOC(RecordType, {}) |
| 1432 | DEF_TRAVERSE_TYPELOC(EnumType, {}) |
| 1433 | DEF_TRAVERSE_TYPELOC(TemplateTypeParmType, {}) |
| 1434 | DEF_TRAVERSE_TYPELOC(SubstTemplateTypeParmType, { |
| 1435 | TRY_TO(TraverseType(TL.getTypePtr()->getReplacementType())); |
| 1436 | }) |
| 1437 | DEF_TRAVERSE_TYPELOC(SubstTemplateTypeParmPackType, { |
| 1438 | TRY_TO(TraverseTemplateArgument(TL.getTypePtr()->getArgumentPack())); |
| 1439 | }) |
| 1440 | |
| 1441 | // FIXME: use the loc for the template name? |
| 1442 | DEF_TRAVERSE_TYPELOC(TemplateSpecializationType, { |
| 1443 | TRY_TO(TraverseTemplateName(TL.getTypePtr()->getTemplateName())); |
| 1444 | for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) { |
| 1445 | TRY_TO(TraverseTemplateArgumentLoc(TL.getArgLoc(I))); |
| 1446 | } |
| 1447 | }) |
| 1448 | |
| 1449 | DEF_TRAVERSE_TYPELOC(InjectedClassNameType, {}) |
| 1450 | |
| 1451 | DEF_TRAVERSE_TYPELOC(ParenType, { TRY_TO(TraverseTypeLoc(TL.getInnerLoc())); }) |
| 1452 | |
| 1453 | DEF_TRAVERSE_TYPELOC(MacroQualifiedType, |
| 1454 | { TRY_TO(TraverseTypeLoc(TL.getInnerLoc())); }) |
| 1455 | |
| 1456 | DEF_TRAVERSE_TYPELOC(AttributedType, |
| 1457 | { TRY_TO(TraverseTypeLoc(TL.getModifiedLoc())); }) |
| 1458 | |
| 1459 | DEF_TRAVERSE_TYPELOC(CountAttributedType, |
| 1460 | { TRY_TO(TraverseTypeLoc(TL.getInnerLoc())); }) |
| 1461 | |
| 1462 | DEF_TRAVERSE_TYPELOC(BTFTagAttributedType, |
| 1463 | { TRY_TO(TraverseTypeLoc(TL.getWrappedLoc())); }) |
| 1464 | |
| 1465 | DEF_TRAVERSE_TYPELOC(HLSLAttributedResourceType, |
| 1466 | { TRY_TO(TraverseTypeLoc(TL.getWrappedLoc())); }) |
| 1467 | |
| 1468 | DEF_TRAVERSE_TYPELOC(HLSLInlineSpirvType, |
| 1469 | { TRY_TO(TraverseType(TL.getType())); }) |
| 1470 | |
| 1471 | DEF_TRAVERSE_TYPELOC(ElaboratedType, { |
| 1472 | if (TL.getQualifierLoc()) { |
| 1473 | TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc())); |
| 1474 | } |
| 1475 | TRY_TO(TraverseTypeLoc(TL.getNamedTypeLoc())); |
| 1476 | }) |
| 1477 | |
| 1478 | DEF_TRAVERSE_TYPELOC(DependentNameType, { |
| 1479 | TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc())); |
| 1480 | }) |
| 1481 | |
| 1482 | DEF_TRAVERSE_TYPELOC(DependentTemplateSpecializationType, { |
| 1483 | if (TL.getQualifierLoc()) { |
| 1484 | TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc())); |
| 1485 | } |
| 1486 | |
| 1487 | for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) { |
| 1488 | TRY_TO(TraverseTemplateArgumentLoc(TL.getArgLoc(I))); |
| 1489 | } |
| 1490 | }) |
| 1491 | |
| 1492 | DEF_TRAVERSE_TYPELOC(PackExpansionType, |
| 1493 | { TRY_TO(TraverseTypeLoc(TL.getPatternLoc())); }) |
| 1494 | |
| 1495 | DEF_TRAVERSE_TYPELOC(ObjCTypeParamType, { |
| 1496 | for (unsigned I = 0, N = TL.getNumProtocols(); I != N; ++I) { |
| 1497 | ObjCProtocolLoc ProtocolLoc(TL.getProtocol(I), TL.getProtocolLoc(I)); |
| 1498 | TRY_TO(TraverseObjCProtocolLoc(ProtocolLoc)); |
| 1499 | } |
| 1500 | }) |
| 1501 | |
| 1502 | DEF_TRAVERSE_TYPELOC(ObjCInterfaceType, {}) |
| 1503 | |
| 1504 | DEF_TRAVERSE_TYPELOC(ObjCObjectType, { |
| 1505 | // We have to watch out here because an ObjCInterfaceType's base |
| 1506 | // type is itself. |
| 1507 | if (TL.getTypePtr()->getBaseType().getTypePtr() != TL.getTypePtr()) |
| 1508 | TRY_TO(TraverseTypeLoc(TL.getBaseLoc())); |
| 1509 | for (unsigned i = 0, n = TL.getNumTypeArgs(); i != n; ++i) |
| 1510 | TRY_TO(TraverseTypeLoc(TL.getTypeArgTInfo(i)->getTypeLoc())); |
| 1511 | for (unsigned I = 0, N = TL.getNumProtocols(); I != N; ++I) { |
| 1512 | ObjCProtocolLoc ProtocolLoc(TL.getProtocol(I), TL.getProtocolLoc(I)); |
| 1513 | TRY_TO(TraverseObjCProtocolLoc(ProtocolLoc)); |
| 1514 | } |
| 1515 | }) |
| 1516 | |
| 1517 | DEF_TRAVERSE_TYPELOC(ObjCObjectPointerType, |
| 1518 | { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); }) |
| 1519 | |
| 1520 | DEF_TRAVERSE_TYPELOC(AtomicType, { TRY_TO(TraverseTypeLoc(TL.getValueLoc())); }) |
| 1521 | |
| 1522 | DEF_TRAVERSE_TYPELOC(PipeType, { TRY_TO(TraverseTypeLoc(TL.getValueLoc())); }) |
| 1523 | |
| 1524 | DEF_TRAVERSE_TYPELOC(BitIntType, {}) |
| 1525 | DEF_TRAVERSE_TYPELOC(DependentBitIntType, { |
| 1526 | TRY_TO(TraverseStmt(TL.getTypePtr()->getNumBitsExpr())); |
| 1527 | }) |
| 1528 | |
| 1529 | #undef DEF_TRAVERSE_TYPELOC |
| 1530 | |
| 1531 | // ----------------- Decl traversal ----------------- |
| 1532 | // |
| 1533 | // For a Decl, we automate (in the DEF_TRAVERSE_DECL macro) traversing |
| 1534 | // the children that come from the DeclContext associated with it. |
| 1535 | // Therefore each Traverse* only needs to worry about children other |
| 1536 | // than those. |
| 1537 | |
| 1538 | template <typename Derived> |
| 1539 | bool RecursiveASTVisitor<Derived>::canIgnoreChildDeclWhileTraversingDeclContext( |
| 1540 | const Decl *Child) { |
| 1541 | // BlockDecls are traversed through BlockExprs, |
| 1542 | // CapturedDecls are traversed through CapturedStmts. |
| 1543 | if (isa<BlockDecl>(Val: Child) || isa<CapturedDecl>(Val: Child)) |
| 1544 | return true; |
| 1545 | // Lambda classes are traversed through LambdaExprs. |
| 1546 | if (const CXXRecordDecl* Cls = dyn_cast<CXXRecordDecl>(Val: Child)) |
| 1547 | return Cls->isLambda(); |
| 1548 | return false; |
| 1549 | } |
| 1550 | |
| 1551 | template <typename Derived> |
| 1552 | bool RecursiveASTVisitor<Derived>::TraverseDeclContextHelper(DeclContext *DC) { |
| 1553 | if (!DC) |
| 1554 | return true; |
| 1555 | |
| 1556 | for (auto *Child : DC->decls()) { |
| 1557 | if (!canIgnoreChildDeclWhileTraversingDeclContext(Child)) |
| 1558 | TRY_TO(TraverseDecl(Child)); |
| 1559 | } |
| 1560 | |
| 1561 | return true; |
| 1562 | } |
| 1563 | |
| 1564 | // This macro makes available a variable D, the passed-in decl. |
| 1565 | #define DEF_TRAVERSE_DECL(DECL, CODE) \ |
| 1566 | template <typename Derived> \ |
| 1567 | bool RecursiveASTVisitor<Derived>::Traverse##DECL(DECL *D) { \ |
| 1568 | bool ShouldVisitChildren = true; \ |
| 1569 | bool ReturnValue = true; \ |
| 1570 | if (!getDerived().shouldTraversePostOrder()) \ |
| 1571 | TRY_TO(WalkUpFrom##DECL(D)); \ |
| 1572 | { CODE; } \ |
| 1573 | if (ReturnValue && ShouldVisitChildren) \ |
| 1574 | TRY_TO(TraverseDeclContextHelper(dyn_cast<DeclContext>(D))); \ |
| 1575 | if (ReturnValue) { \ |
| 1576 | /* Visit any attributes attached to this declaration. */ \ |
| 1577 | for (auto *I : D->attrs()) \ |
| 1578 | TRY_TO(getDerived().TraverseAttr(I)); \ |
| 1579 | } \ |
| 1580 | if (ReturnValue && getDerived().shouldTraversePostOrder()) \ |
| 1581 | TRY_TO(WalkUpFrom##DECL(D)); \ |
| 1582 | return ReturnValue; \ |
| 1583 | } |
| 1584 | |
| 1585 | DEF_TRAVERSE_DECL(AccessSpecDecl, {}) |
| 1586 | |
| 1587 | DEF_TRAVERSE_DECL(BlockDecl, { |
| 1588 | if (TypeSourceInfo *TInfo = D->getSignatureAsWritten()) |
| 1589 | TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc())); |
| 1590 | TRY_TO(TraverseStmt(D->getBody())); |
| 1591 | for (const auto &I : D->captures()) { |
| 1592 | if (I.hasCopyExpr()) { |
| 1593 | TRY_TO(TraverseStmt(I.getCopyExpr())); |
| 1594 | } |
| 1595 | } |
| 1596 | ShouldVisitChildren = false; |
| 1597 | }) |
| 1598 | |
| 1599 | DEF_TRAVERSE_DECL(OutlinedFunctionDecl, { |
| 1600 | TRY_TO(TraverseStmt(D->getBody())); |
| 1601 | ShouldVisitChildren = false; |
| 1602 | }) |
| 1603 | |
| 1604 | DEF_TRAVERSE_DECL(CapturedDecl, { |
| 1605 | TRY_TO(TraverseStmt(D->getBody())); |
| 1606 | ShouldVisitChildren = false; |
| 1607 | }) |
| 1608 | |
| 1609 | DEF_TRAVERSE_DECL(EmptyDecl, {}) |
| 1610 | |
| 1611 | DEF_TRAVERSE_DECL(HLSLBufferDecl, {}) |
| 1612 | |
| 1613 | DEF_TRAVERSE_DECL(HLSLRootSignatureDecl, {}) |
| 1614 | |
| 1615 | DEF_TRAVERSE_DECL(LifetimeExtendedTemporaryDecl, { |
| 1616 | TRY_TO(TraverseStmt(D->getTemporaryExpr())); |
| 1617 | }) |
| 1618 | |
| 1619 | DEF_TRAVERSE_DECL(FileScopeAsmDecl, |
| 1620 | { TRY_TO(TraverseStmt(D->getAsmStringExpr())); }) |
| 1621 | |
| 1622 | DEF_TRAVERSE_DECL(TopLevelStmtDecl, { TRY_TO(TraverseStmt(D->getStmt())); }) |
| 1623 | |
| 1624 | DEF_TRAVERSE_DECL(ImportDecl, {}) |
| 1625 | |
| 1626 | DEF_TRAVERSE_DECL(FriendDecl, { |
| 1627 | // Friend is either decl or a type. |
| 1628 | if (D->getFriendType()) { |
| 1629 | TRY_TO(TraverseTypeLoc(D->getFriendType()->getTypeLoc())); |
| 1630 | // Traverse any CXXRecordDecl owned by this type, since |
| 1631 | // it will not be in the parent context: |
| 1632 | if (auto *ET = D->getFriendType()->getType()->getAs<ElaboratedType>()) |
| 1633 | TRY_TO(TraverseDecl(ET->getOwnedTagDecl())); |
| 1634 | } else { |
| 1635 | TRY_TO(TraverseDecl(D->getFriendDecl())); |
| 1636 | } |
| 1637 | }) |
| 1638 | |
| 1639 | DEF_TRAVERSE_DECL(FriendTemplateDecl, { |
| 1640 | if (D->getFriendType()) |
| 1641 | TRY_TO(TraverseTypeLoc(D->getFriendType()->getTypeLoc())); |
| 1642 | else |
| 1643 | TRY_TO(TraverseDecl(D->getFriendDecl())); |
| 1644 | for (unsigned I = 0, E = D->getNumTemplateParameters(); I < E; ++I) { |
| 1645 | TemplateParameterList *TPL = D->getTemplateParameterList(I); |
| 1646 | for (TemplateParameterList::iterator ITPL = TPL->begin(), ETPL = TPL->end(); |
| 1647 | ITPL != ETPL; ++ITPL) { |
| 1648 | TRY_TO(TraverseDecl(*ITPL)); |
| 1649 | } |
| 1650 | } |
| 1651 | }) |
| 1652 | |
| 1653 | DEF_TRAVERSE_DECL(LinkageSpecDecl, {}) |
| 1654 | |
| 1655 | DEF_TRAVERSE_DECL(ExportDecl, {}) |
| 1656 | |
| 1657 | DEF_TRAVERSE_DECL(ObjCPropertyImplDecl, {// FIXME: implement this |
| 1658 | }) |
| 1659 | |
| 1660 | DEF_TRAVERSE_DECL(StaticAssertDecl, { |
| 1661 | TRY_TO(TraverseStmt(D->getAssertExpr())); |
| 1662 | TRY_TO(TraverseStmt(D->getMessage())); |
| 1663 | }) |
| 1664 | |
| 1665 | DEF_TRAVERSE_DECL(TranslationUnitDecl, { |
| 1666 | // Code in an unnamed namespace shows up automatically in |
| 1667 | // decls_begin()/decls_end(). Thus we don't need to recurse on |
| 1668 | // D->getAnonymousNamespace(). |
| 1669 | |
| 1670 | // If the traversal scope is set, then consider them to be the children of |
| 1671 | // the TUDecl, rather than traversing (and loading?) all top-level decls. |
| 1672 | auto Scope = D->getASTContext().getTraversalScope(); |
| 1673 | bool HasLimitedScope = |
| 1674 | Scope.size() != 1 || !isa<TranslationUnitDecl>(Scope.front()); |
| 1675 | if (HasLimitedScope) { |
| 1676 | ShouldVisitChildren = false; // we'll do that here instead |
| 1677 | for (auto *Child : Scope) { |
| 1678 | if (!canIgnoreChildDeclWhileTraversingDeclContext(Child)) |
| 1679 | TRY_TO(TraverseDecl(Child)); |
| 1680 | } |
| 1681 | } |
| 1682 | }) |
| 1683 | |
| 1684 | DEF_TRAVERSE_DECL(PragmaCommentDecl, {}) |
| 1685 | |
| 1686 | DEF_TRAVERSE_DECL(PragmaDetectMismatchDecl, {}) |
| 1687 | |
| 1688 | DEF_TRAVERSE_DECL(ExternCContextDecl, {}) |
| 1689 | |
| 1690 | DEF_TRAVERSE_DECL(NamespaceAliasDecl, { |
| 1691 | TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); |
| 1692 | |
| 1693 | // We shouldn't traverse an aliased namespace, since it will be |
| 1694 | // defined (and, therefore, traversed) somewhere else. |
| 1695 | ShouldVisitChildren = false; |
| 1696 | }) |
| 1697 | |
| 1698 | DEF_TRAVERSE_DECL(LabelDecl, {// There is no code in a LabelDecl. |
| 1699 | }) |
| 1700 | |
| 1701 | DEF_TRAVERSE_DECL( |
| 1702 | NamespaceDecl, |
| 1703 | {// Code in an unnamed namespace shows up automatically in |
| 1704 | // decls_begin()/decls_end(). Thus we don't need to recurse on |
| 1705 | // D->getAnonymousNamespace(). |
| 1706 | }) |
| 1707 | |
| 1708 | DEF_TRAVERSE_DECL(ObjCCompatibleAliasDecl, {// FIXME: implement |
| 1709 | }) |
| 1710 | |
| 1711 | DEF_TRAVERSE_DECL(ObjCCategoryDecl, { |
| 1712 | if (ObjCTypeParamList *typeParamList = D->getTypeParamList()) { |
| 1713 | for (auto typeParam : *typeParamList) { |
| 1714 | TRY_TO(TraverseObjCTypeParamDecl(typeParam)); |
| 1715 | } |
| 1716 | } |
| 1717 | for (auto It : llvm::zip(D->protocols(), D->protocol_locs())) { |
| 1718 | ObjCProtocolLoc ProtocolLoc(std::get<0>(It), std::get<1>(It)); |
| 1719 | TRY_TO(TraverseObjCProtocolLoc(ProtocolLoc)); |
| 1720 | } |
| 1721 | }) |
| 1722 | |
| 1723 | DEF_TRAVERSE_DECL(ObjCCategoryImplDecl, {// FIXME: implement |
| 1724 | }) |
| 1725 | |
| 1726 | DEF_TRAVERSE_DECL(ObjCImplementationDecl, {// FIXME: implement |
| 1727 | }) |
| 1728 | |
| 1729 | DEF_TRAVERSE_DECL(ObjCInterfaceDecl, { |
| 1730 | if (ObjCTypeParamList *typeParamList = D->getTypeParamListAsWritten()) { |
| 1731 | for (auto typeParam : *typeParamList) { |
| 1732 | TRY_TO(TraverseObjCTypeParamDecl(typeParam)); |
| 1733 | } |
| 1734 | } |
| 1735 | |
| 1736 | if (TypeSourceInfo *superTInfo = D->getSuperClassTInfo()) { |
| 1737 | TRY_TO(TraverseTypeLoc(superTInfo->getTypeLoc())); |
| 1738 | } |
| 1739 | if (D->isThisDeclarationADefinition()) { |
| 1740 | for (auto It : llvm::zip(D->protocols(), D->protocol_locs())) { |
| 1741 | ObjCProtocolLoc ProtocolLoc(std::get<0>(It), std::get<1>(It)); |
| 1742 | TRY_TO(TraverseObjCProtocolLoc(ProtocolLoc)); |
| 1743 | } |
| 1744 | } |
| 1745 | }) |
| 1746 | |
| 1747 | DEF_TRAVERSE_DECL(ObjCProtocolDecl, { |
| 1748 | if (D->isThisDeclarationADefinition()) { |
| 1749 | for (auto It : llvm::zip(D->protocols(), D->protocol_locs())) { |
| 1750 | ObjCProtocolLoc ProtocolLoc(std::get<0>(It), std::get<1>(It)); |
| 1751 | TRY_TO(TraverseObjCProtocolLoc(ProtocolLoc)); |
| 1752 | } |
| 1753 | } |
| 1754 | }) |
| 1755 | |
| 1756 | DEF_TRAVERSE_DECL(ObjCMethodDecl, { |
| 1757 | if (D->getReturnTypeSourceInfo()) { |
| 1758 | TRY_TO(TraverseTypeLoc(D->getReturnTypeSourceInfo()->getTypeLoc())); |
| 1759 | } |
| 1760 | for (ParmVarDecl *Parameter : D->parameters()) { |
| 1761 | TRY_TO(TraverseDecl(Parameter)); |
| 1762 | } |
| 1763 | if (D->isThisDeclarationADefinition()) { |
| 1764 | TRY_TO(TraverseStmt(D->getBody())); |
| 1765 | } |
| 1766 | ShouldVisitChildren = false; |
| 1767 | }) |
| 1768 | |
| 1769 | DEF_TRAVERSE_DECL(ObjCTypeParamDecl, { |
| 1770 | if (D->hasExplicitBound()) { |
| 1771 | TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc())); |
| 1772 | // We shouldn't traverse D->getTypeForDecl(); it's a result of |
| 1773 | // declaring the type alias, not something that was written in the |
| 1774 | // source. |
| 1775 | } |
| 1776 | }) |
| 1777 | |
| 1778 | DEF_TRAVERSE_DECL(ObjCPropertyDecl, { |
| 1779 | if (D->getTypeSourceInfo()) |
| 1780 | TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc())); |
| 1781 | else |
| 1782 | TRY_TO(TraverseType(D->getType())); |
| 1783 | ShouldVisitChildren = false; |
| 1784 | }) |
| 1785 | |
| 1786 | DEF_TRAVERSE_DECL(UsingDecl, { |
| 1787 | TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); |
| 1788 | TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo())); |
| 1789 | }) |
| 1790 | |
| 1791 | DEF_TRAVERSE_DECL(UsingEnumDecl, |
| 1792 | { TRY_TO(TraverseTypeLoc(D->getEnumTypeLoc())); }) |
| 1793 | |
| 1794 | DEF_TRAVERSE_DECL(UsingPackDecl, {}) |
| 1795 | |
| 1796 | DEF_TRAVERSE_DECL(UsingDirectiveDecl, { |
| 1797 | TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); |
| 1798 | }) |
| 1799 | |
| 1800 | DEF_TRAVERSE_DECL(UsingShadowDecl, {}) |
| 1801 | |
| 1802 | DEF_TRAVERSE_DECL(ConstructorUsingShadowDecl, {}) |
| 1803 | |
| 1804 | DEF_TRAVERSE_DECL(OMPThreadPrivateDecl, { |
| 1805 | for (auto *I : D->varlist()) { |
| 1806 | TRY_TO(TraverseStmt(I)); |
| 1807 | } |
| 1808 | }) |
| 1809 | |
| 1810 | DEF_TRAVERSE_DECL(OMPRequiresDecl, { |
| 1811 | for (auto *C : D->clauselists()) { |
| 1812 | TRY_TO(TraverseOMPClause(C)); |
| 1813 | } |
| 1814 | }) |
| 1815 | |
| 1816 | DEF_TRAVERSE_DECL(OMPDeclareReductionDecl, { |
| 1817 | TRY_TO(TraverseStmt(D->getCombiner())); |
| 1818 | if (auto *Initializer = D->getInitializer()) |
| 1819 | TRY_TO(TraverseStmt(Initializer)); |
| 1820 | TRY_TO(TraverseType(D->getType())); |
| 1821 | return true; |
| 1822 | }) |
| 1823 | |
| 1824 | DEF_TRAVERSE_DECL(OMPDeclareMapperDecl, { |
| 1825 | for (auto *C : D->clauselists()) |
| 1826 | TRY_TO(TraverseOMPClause(C)); |
| 1827 | TRY_TO(TraverseType(D->getType())); |
| 1828 | return true; |
| 1829 | }) |
| 1830 | |
| 1831 | DEF_TRAVERSE_DECL(OMPCapturedExprDecl, { TRY_TO(TraverseVarHelper(D)); }) |
| 1832 | |
| 1833 | DEF_TRAVERSE_DECL(OMPAllocateDecl, { |
| 1834 | for (auto *I : D->varlist()) |
| 1835 | TRY_TO(TraverseStmt(I)); |
| 1836 | for (auto *C : D->clauselists()) |
| 1837 | TRY_TO(TraverseOMPClause(C)); |
| 1838 | }) |
| 1839 | |
| 1840 | DEF_TRAVERSE_DECL(OpenACCDeclareDecl, |
| 1841 | { TRY_TO(VisitOpenACCClauseList(D->clauses())); }) |
| 1842 | |
| 1843 | DEF_TRAVERSE_DECL(OpenACCRoutineDecl, { |
| 1844 | TRY_TO(TraverseStmt(D->getFunctionReference())); |
| 1845 | TRY_TO(VisitOpenACCClauseList(D->clauses())); |
| 1846 | }) |
| 1847 | |
| 1848 | // A helper method for TemplateDecl's children. |
| 1849 | template <typename Derived> |
| 1850 | bool RecursiveASTVisitor<Derived>::TraverseTemplateParameterListHelper( |
| 1851 | TemplateParameterList *TPL) { |
| 1852 | if (TPL) { |
| 1853 | for (NamedDecl *D : *TPL) { |
| 1854 | TRY_TO(TraverseDecl(D)); |
| 1855 | } |
| 1856 | if (Expr *RequiresClause = TPL->getRequiresClause()) { |
| 1857 | TRY_TO(TraverseStmt(RequiresClause)); |
| 1858 | } |
| 1859 | } |
| 1860 | return true; |
| 1861 | } |
| 1862 | |
| 1863 | template <typename Derived> |
| 1864 | template <typename T> |
| 1865 | bool RecursiveASTVisitor<Derived>::TraverseDeclTemplateParameterLists(T *D) { |
| 1866 | for (unsigned i = 0; i < D->getNumTemplateParameterLists(); i++) { |
| 1867 | TemplateParameterList *TPL = D->getTemplateParameterList(i); |
| 1868 | TraverseTemplateParameterListHelper(TPL); |
| 1869 | } |
| 1870 | return true; |
| 1871 | } |
| 1872 | |
| 1873 | template <typename Derived> |
| 1874 | bool RecursiveASTVisitor<Derived>::TraverseTemplateInstantiations( |
| 1875 | ClassTemplateDecl *D) { |
| 1876 | for (auto *SD : D->specializations()) { |
| 1877 | for (auto *RD : SD->redecls()) { |
| 1878 | assert(!cast<CXXRecordDecl>(RD)->isInjectedClassName()); |
| 1879 | switch ( |
| 1880 | cast<ClassTemplateSpecializationDecl>(Val: RD)->getSpecializationKind()) { |
| 1881 | // Visit the implicit instantiations with the requested pattern. |
| 1882 | case TSK_Undeclared: |
| 1883 | case TSK_ImplicitInstantiation: |
| 1884 | TRY_TO(TraverseDecl(RD)); |
| 1885 | break; |
| 1886 | |
| 1887 | // We don't need to do anything on an explicit instantiation |
| 1888 | // or explicit specialization because there will be an explicit |
| 1889 | // node for it elsewhere. |
| 1890 | case TSK_ExplicitInstantiationDeclaration: |
| 1891 | case TSK_ExplicitInstantiationDefinition: |
| 1892 | case TSK_ExplicitSpecialization: |
| 1893 | break; |
| 1894 | } |
| 1895 | } |
| 1896 | } |
| 1897 | |
| 1898 | return true; |
| 1899 | } |
| 1900 | |
| 1901 | template <typename Derived> |
| 1902 | bool RecursiveASTVisitor<Derived>::TraverseTemplateInstantiations( |
| 1903 | VarTemplateDecl *D) { |
| 1904 | for (auto *SD : D->specializations()) { |
| 1905 | for (auto *RD : SD->redecls()) { |
| 1906 | switch ( |
| 1907 | cast<VarTemplateSpecializationDecl>(Val: RD)->getSpecializationKind()) { |
| 1908 | case TSK_Undeclared: |
| 1909 | case TSK_ImplicitInstantiation: |
| 1910 | TRY_TO(TraverseDecl(RD)); |
| 1911 | break; |
| 1912 | |
| 1913 | case TSK_ExplicitInstantiationDeclaration: |
| 1914 | case TSK_ExplicitInstantiationDefinition: |
| 1915 | case TSK_ExplicitSpecialization: |
| 1916 | break; |
| 1917 | } |
| 1918 | } |
| 1919 | } |
| 1920 | |
| 1921 | return true; |
| 1922 | } |
| 1923 | |
| 1924 | // A helper method for traversing the instantiations of a |
| 1925 | // function while skipping its specializations. |
| 1926 | template <typename Derived> |
| 1927 | bool RecursiveASTVisitor<Derived>::TraverseTemplateInstantiations( |
| 1928 | FunctionTemplateDecl *D) { |
| 1929 | for (auto *FD : D->specializations()) { |
| 1930 | for (auto *RD : FD->redecls()) { |
| 1931 | switch (RD->getTemplateSpecializationKind()) { |
| 1932 | case TSK_Undeclared: |
| 1933 | case TSK_ImplicitInstantiation: |
| 1934 | // We don't know what kind of FunctionDecl this is. |
| 1935 | TRY_TO(TraverseDecl(RD)); |
| 1936 | break; |
| 1937 | |
| 1938 | // FIXME: For now traverse explicit instantiations here. Change that |
| 1939 | // once they are represented as dedicated nodes in the AST. |
| 1940 | case TSK_ExplicitInstantiationDeclaration: |
| 1941 | case TSK_ExplicitInstantiationDefinition: |
| 1942 | TRY_TO(TraverseDecl(RD)); |
| 1943 | break; |
| 1944 | |
| 1945 | case TSK_ExplicitSpecialization: |
| 1946 | break; |
| 1947 | } |
| 1948 | } |
| 1949 | } |
| 1950 | |
| 1951 | return true; |
| 1952 | } |
| 1953 | |
| 1954 | // This macro unifies the traversal of class, variable and function |
| 1955 | // template declarations. |
| 1956 | #define DEF_TRAVERSE_TMPL_DECL(TMPLDECLKIND) \ |
| 1957 | DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplateDecl, { \ |
| 1958 | TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); \ |
| 1959 | TRY_TO(TraverseDecl(D->getTemplatedDecl())); \ |
| 1960 | \ |
| 1961 | /* By default, we do not traverse the instantiations of \ |
| 1962 | class templates since they do not appear in the user code. The \ |
| 1963 | following code optionally traverses them. \ |
| 1964 | \ |
| 1965 | We only traverse the class instantiations when we see the canonical \ |
| 1966 | declaration of the template, to ensure we only visit them once. */ \ |
| 1967 | if (getDerived().shouldVisitTemplateInstantiations() && \ |
| 1968 | D == D->getCanonicalDecl()) \ |
| 1969 | TRY_TO(TraverseTemplateInstantiations(D)); \ |
| 1970 | \ |
| 1971 | /* Note that getInstantiatedFromMemberTemplate() is just a link \ |
| 1972 | from a template instantiation back to the template from which \ |
| 1973 | it was instantiated, and thus should not be traversed. */ \ |
| 1974 | }) |
| 1975 | |
| 1976 | DEF_TRAVERSE_TMPL_DECL(Class) |
| 1977 | DEF_TRAVERSE_TMPL_DECL(Var) |
| 1978 | DEF_TRAVERSE_TMPL_DECL(Function) |
| 1979 | |
| 1980 | DEF_TRAVERSE_DECL(TemplateTemplateParmDecl, { |
| 1981 | // D is the "T" in something like |
| 1982 | // template <template <typename> class T> class container { }; |
| 1983 | TRY_TO(TraverseDecl(D->getTemplatedDecl())); |
| 1984 | if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) |
| 1985 | TRY_TO(TraverseTemplateArgumentLoc(D->getDefaultArgument())); |
| 1986 | TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); |
| 1987 | }) |
| 1988 | |
| 1989 | DEF_TRAVERSE_DECL(BuiltinTemplateDecl, { |
| 1990 | TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); |
| 1991 | }) |
| 1992 | |
| 1993 | template <typename Derived> |
| 1994 | bool RecursiveASTVisitor<Derived>::TraverseTemplateTypeParamDeclConstraints( |
| 1995 | const TemplateTypeParmDecl *D) { |
| 1996 | if (const auto *TC = D->getTypeConstraint()) |
| 1997 | TRY_TO(TraverseTypeConstraint(TC)); |
| 1998 | return true; |
| 1999 | } |
| 2000 | |
| 2001 | DEF_TRAVERSE_DECL(TemplateTypeParmDecl, { |
| 2002 | // D is the "T" in something like "template<typename T> class vector;" |
| 2003 | if (D->getTypeForDecl()) |
| 2004 | TRY_TO(TraverseType(QualType(D->getTypeForDecl(), 0))); |
| 2005 | TRY_TO(TraverseTemplateTypeParamDeclConstraints(D)); |
| 2006 | if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) |
| 2007 | TRY_TO(TraverseTemplateArgumentLoc(D->getDefaultArgument())); |
| 2008 | }) |
| 2009 | |
| 2010 | DEF_TRAVERSE_DECL(TypedefDecl, { |
| 2011 | TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc())); |
| 2012 | // We shouldn't traverse D->getTypeForDecl(); it's a result of |
| 2013 | // declaring the typedef, not something that was written in the |
| 2014 | // source. |
| 2015 | }) |
| 2016 | |
| 2017 | DEF_TRAVERSE_DECL(TypeAliasDecl, { |
| 2018 | TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc())); |
| 2019 | // We shouldn't traverse D->getTypeForDecl(); it's a result of |
| 2020 | // declaring the type alias, not something that was written in the |
| 2021 | // source. |
| 2022 | }) |
| 2023 | |
| 2024 | DEF_TRAVERSE_DECL(TypeAliasTemplateDecl, { |
| 2025 | TRY_TO(TraverseDecl(D->getTemplatedDecl())); |
| 2026 | TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); |
| 2027 | }) |
| 2028 | |
| 2029 | DEF_TRAVERSE_DECL(ConceptDecl, { |
| 2030 | TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); |
| 2031 | TRY_TO(TraverseStmt(D->getConstraintExpr())); |
| 2032 | }) |
| 2033 | |
| 2034 | DEF_TRAVERSE_DECL(UnresolvedUsingTypenameDecl, { |
| 2035 | // A dependent using declaration which was marked with 'typename'. |
| 2036 | // template<class T> class A : public B<T> { using typename B<T>::foo; }; |
| 2037 | TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); |
| 2038 | // We shouldn't traverse D->getTypeForDecl(); it's a result of |
| 2039 | // declaring the type, not something that was written in the |
| 2040 | // source. |
| 2041 | }) |
| 2042 | |
| 2043 | DEF_TRAVERSE_DECL(UnresolvedUsingIfExistsDecl, {}) |
| 2044 | |
| 2045 | DEF_TRAVERSE_DECL(EnumDecl, { |
| 2046 | TRY_TO(TraverseDeclTemplateParameterLists(D)); |
| 2047 | |
| 2048 | TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); |
| 2049 | if (auto *TSI = D->getIntegerTypeSourceInfo()) |
| 2050 | TRY_TO(TraverseTypeLoc(TSI->getTypeLoc())); |
| 2051 | // The enumerators are already traversed by |
| 2052 | // decls_begin()/decls_end(). |
| 2053 | }) |
| 2054 | |
| 2055 | // Helper methods for RecordDecl and its children. |
| 2056 | template <typename Derived> |
| 2057 | bool RecursiveASTVisitor<Derived>::TraverseRecordHelper(RecordDecl *D) { |
| 2058 | // We shouldn't traverse D->getTypeForDecl(); it's a result of |
| 2059 | // declaring the type, not something that was written in the source. |
| 2060 | |
| 2061 | TRY_TO(TraverseDeclTemplateParameterLists(D)); |
| 2062 | TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); |
| 2063 | return true; |
| 2064 | } |
| 2065 | |
| 2066 | template <typename Derived> |
| 2067 | bool RecursiveASTVisitor<Derived>::TraverseCXXBaseSpecifier( |
| 2068 | const CXXBaseSpecifier &Base) { |
| 2069 | TRY_TO(TraverseTypeLoc(Base.getTypeSourceInfo()->getTypeLoc())); |
| 2070 | return true; |
| 2071 | } |
| 2072 | |
| 2073 | template <typename Derived> |
| 2074 | bool RecursiveASTVisitor<Derived>::TraverseCXXRecordHelper(CXXRecordDecl *D) { |
| 2075 | if (!TraverseRecordHelper(D)) |
| 2076 | return false; |
| 2077 | if (D->isCompleteDefinition()) { |
| 2078 | for (const auto &I : D->bases()) { |
| 2079 | TRY_TO(TraverseCXXBaseSpecifier(I)); |
| 2080 | } |
| 2081 | // We don't traverse the friends or the conversions, as they are |
| 2082 | // already in decls_begin()/decls_end(). |
| 2083 | } |
| 2084 | return true; |
| 2085 | } |
| 2086 | |
| 2087 | DEF_TRAVERSE_DECL(RecordDecl, { TRY_TO(TraverseRecordHelper(D)); }) |
| 2088 | |
| 2089 | DEF_TRAVERSE_DECL(CXXRecordDecl, { TRY_TO(TraverseCXXRecordHelper(D)); }) |
| 2090 | |
| 2091 | template <typename Derived> |
| 2092 | bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLocsHelper( |
| 2093 | const TemplateArgumentLoc *TAL, unsigned Count) { |
| 2094 | for (unsigned I = 0; I < Count; ++I) { |
| 2095 | TRY_TO(TraverseTemplateArgumentLoc(TAL[I])); |
| 2096 | } |
| 2097 | return true; |
| 2098 | } |
| 2099 | |
| 2100 | #define DEF_TRAVERSE_TMPL_SPEC_DECL(TMPLDECLKIND, DECLKIND) \ |
| 2101 | DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplateSpecializationDecl, { \ |
| 2102 | /* For implicit instantiations ("set<int> x;"), we don't want to \ |
| 2103 | recurse at all, since the instatiated template isn't written in \ |
| 2104 | the source code anywhere. (Note the instatiated *type* -- \ |
| 2105 | set<int> -- is written, and will still get a callback of \ |
| 2106 | TemplateSpecializationType). For explicit instantiations \ |
| 2107 | ("template set<int>;"), we do need a callback, since this \ |
| 2108 | is the only callback that's made for this instantiation. \ |
| 2109 | We use getTemplateArgsAsWritten() to distinguish. */ \ |
| 2110 | if (const auto *ArgsWritten = D->getTemplateArgsAsWritten()) { \ |
| 2111 | /* The args that remains unspecialized. */ \ |
| 2112 | TRY_TO(TraverseTemplateArgumentLocsHelper( \ |
| 2113 | ArgsWritten->getTemplateArgs(), ArgsWritten->NumTemplateArgs)); \ |
| 2114 | } \ |
| 2115 | \ |
| 2116 | if (getDerived().shouldVisitTemplateInstantiations() || \ |
| 2117 | D->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) { \ |
| 2118 | /* Traverse base definition for explicit specializations */ \ |
| 2119 | TRY_TO(Traverse##DECLKIND##Helper(D)); \ |
| 2120 | } else { \ |
| 2121 | TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); \ |
| 2122 | \ |
| 2123 | /* Returning from here skips traversing the \ |
| 2124 | declaration context of the *TemplateSpecializationDecl \ |
| 2125 | (embedded in the DEF_TRAVERSE_DECL() macro) \ |
| 2126 | which contains the instantiated members of the template. */ \ |
| 2127 | return true; \ |
| 2128 | } \ |
| 2129 | }) |
| 2130 | |
| 2131 | DEF_TRAVERSE_TMPL_SPEC_DECL(Class, CXXRecord) |
| 2132 | DEF_TRAVERSE_TMPL_SPEC_DECL(Var, Var) |
| 2133 | |
| 2134 | #define DEF_TRAVERSE_TMPL_PART_SPEC_DECL(TMPLDECLKIND, DECLKIND) \ |
| 2135 | DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplatePartialSpecializationDecl, { \ |
| 2136 | /* The partial specialization. */ \ |
| 2137 | TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); \ |
| 2138 | /* The args that remains unspecialized. */ \ |
| 2139 | TRY_TO(TraverseTemplateArgumentLocsHelper( \ |
| 2140 | D->getTemplateArgsAsWritten()->getTemplateArgs(), \ |
| 2141 | D->getTemplateArgsAsWritten()->NumTemplateArgs)); \ |
| 2142 | \ |
| 2143 | /* Don't need the *TemplatePartialSpecializationHelper, even \ |
| 2144 | though that's our parent class -- we already visit all the \ |
| 2145 | template args here. */ \ |
| 2146 | TRY_TO(Traverse##DECLKIND##Helper(D)); \ |
| 2147 | \ |
| 2148 | /* Instantiations will have been visited with the primary template. */ \ |
| 2149 | }) |
| 2150 | |
| 2151 | DEF_TRAVERSE_TMPL_PART_SPEC_DECL(Class, CXXRecord) |
| 2152 | DEF_TRAVERSE_TMPL_PART_SPEC_DECL(Var, Var) |
| 2153 | |
| 2154 | DEF_TRAVERSE_DECL(EnumConstantDecl, { TRY_TO(TraverseStmt(D->getInitExpr())); }) |
| 2155 | |
| 2156 | DEF_TRAVERSE_DECL(UnresolvedUsingValueDecl, { |
| 2157 | // Like UnresolvedUsingTypenameDecl, but without the 'typename': |
| 2158 | // template <class T> Class A : public Base<T> { using Base<T>::foo; }; |
| 2159 | TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); |
| 2160 | TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo())); |
| 2161 | }) |
| 2162 | |
| 2163 | DEF_TRAVERSE_DECL(IndirectFieldDecl, {}) |
| 2164 | |
| 2165 | template <typename Derived> |
| 2166 | bool RecursiveASTVisitor<Derived>::TraverseDeclaratorHelper(DeclaratorDecl *D) { |
| 2167 | TRY_TO(TraverseDeclTemplateParameterLists(D)); |
| 2168 | TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); |
| 2169 | if (D->getTypeSourceInfo()) |
| 2170 | TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc())); |
| 2171 | else |
| 2172 | TRY_TO(TraverseType(D->getType())); |
| 2173 | return true; |
| 2174 | } |
| 2175 | |
| 2176 | DEF_TRAVERSE_DECL(DecompositionDecl, { |
| 2177 | TRY_TO(TraverseVarHelper(D)); |
| 2178 | for (auto *Binding : D->bindings()) { |
| 2179 | TRY_TO(TraverseDecl(Binding)); |
| 2180 | } |
| 2181 | }) |
| 2182 | |
| 2183 | DEF_TRAVERSE_DECL(BindingDecl, { |
| 2184 | if (getDerived().shouldVisitImplicitCode()) { |
| 2185 | TRY_TO(TraverseStmt(D->getBinding())); |
| 2186 | if (const auto HoldingVar = D->getHoldingVar()) |
| 2187 | TRY_TO(TraverseDecl(HoldingVar)); |
| 2188 | } |
| 2189 | }) |
| 2190 | |
| 2191 | DEF_TRAVERSE_DECL(MSPropertyDecl, { TRY_TO(TraverseDeclaratorHelper(D)); }) |
| 2192 | |
| 2193 | DEF_TRAVERSE_DECL(MSGuidDecl, {}) |
| 2194 | DEF_TRAVERSE_DECL(UnnamedGlobalConstantDecl, {}) |
| 2195 | |
| 2196 | DEF_TRAVERSE_DECL(TemplateParamObjectDecl, {}) |
| 2197 | |
| 2198 | DEF_TRAVERSE_DECL(FieldDecl, { |
| 2199 | TRY_TO(TraverseDeclaratorHelper(D)); |
| 2200 | if (D->isBitField()) |
| 2201 | TRY_TO(TraverseStmt(D->getBitWidth())); |
| 2202 | if (D->hasInClassInitializer()) |
| 2203 | TRY_TO(TraverseStmt(D->getInClassInitializer())); |
| 2204 | }) |
| 2205 | |
| 2206 | DEF_TRAVERSE_DECL(ObjCAtDefsFieldDecl, { |
| 2207 | TRY_TO(TraverseDeclaratorHelper(D)); |
| 2208 | if (D->isBitField()) |
| 2209 | TRY_TO(TraverseStmt(D->getBitWidth())); |
| 2210 | // FIXME: implement the rest. |
| 2211 | }) |
| 2212 | |
| 2213 | DEF_TRAVERSE_DECL(ObjCIvarDecl, { |
| 2214 | TRY_TO(TraverseDeclaratorHelper(D)); |
| 2215 | if (D->isBitField()) |
| 2216 | TRY_TO(TraverseStmt(D->getBitWidth())); |
| 2217 | // FIXME: implement the rest. |
| 2218 | }) |
| 2219 | |
| 2220 | template <typename Derived> |
| 2221 | bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) { |
| 2222 | TRY_TO(TraverseDeclTemplateParameterLists(D)); |
| 2223 | TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); |
| 2224 | TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo())); |
| 2225 | |
| 2226 | // If we're an explicit template specialization, iterate over the |
| 2227 | // template args that were explicitly specified. If we were doing |
| 2228 | // this in typing order, we'd do it between the return type and |
| 2229 | // the function args, but both are handled by the FunctionTypeLoc |
| 2230 | // above, so we have to choose one side. I've decided to do before. |
| 2231 | if (const FunctionTemplateSpecializationInfo *FTSI = |
| 2232 | D->getTemplateSpecializationInfo()) { |
| 2233 | if (FTSI->getTemplateSpecializationKind() != TSK_Undeclared && |
| 2234 | FTSI->getTemplateSpecializationKind() != TSK_ImplicitInstantiation) { |
| 2235 | // A specialization might not have explicit template arguments if it has |
| 2236 | // a templated return type and concrete arguments. |
| 2237 | if (const ASTTemplateArgumentListInfo *TALI = |
| 2238 | FTSI->TemplateArgumentsAsWritten) { |
| 2239 | TRY_TO(TraverseTemplateArgumentLocsHelper(TALI->getTemplateArgs(), |
| 2240 | TALI->NumTemplateArgs)); |
| 2241 | } |
| 2242 | } |
| 2243 | } else if (const DependentFunctionTemplateSpecializationInfo *DFSI = |
| 2244 | D->getDependentSpecializationInfo()) { |
| 2245 | if (const ASTTemplateArgumentListInfo *TALI = |
| 2246 | DFSI->TemplateArgumentsAsWritten) { |
| 2247 | TRY_TO(TraverseTemplateArgumentLocsHelper(TALI->getTemplateArgs(), |
| 2248 | TALI->NumTemplateArgs)); |
| 2249 | } |
| 2250 | } |
| 2251 | |
| 2252 | // Visit the function type itself, which can be either |
| 2253 | // FunctionNoProtoType or FunctionProtoType, or a typedef. This |
| 2254 | // also covers the return type and the function parameters, |
| 2255 | // including exception specifications. |
| 2256 | if (TypeSourceInfo *TSI = D->getTypeSourceInfo()) { |
| 2257 | TRY_TO(TraverseTypeLoc(TSI->getTypeLoc())); |
| 2258 | } else if (getDerived().shouldVisitImplicitCode()) { |
| 2259 | // Visit parameter variable declarations of the implicit function |
| 2260 | // if the traverser is visiting implicit code. Parameter variable |
| 2261 | // declarations do not have valid TypeSourceInfo, so to visit them |
| 2262 | // we need to traverse the declarations explicitly. |
| 2263 | for (ParmVarDecl *Parameter : D->parameters()) { |
| 2264 | TRY_TO(TraverseDecl(Parameter)); |
| 2265 | } |
| 2266 | } |
| 2267 | |
| 2268 | // Visit the trailing requires clause, if any. |
| 2269 | if (const AssociatedConstraint &TrailingRequiresClause = |
| 2270 | D->getTrailingRequiresClause()) { |
| 2271 | TRY_TO(TraverseStmt( |
| 2272 | const_cast<Expr *>(TrailingRequiresClause.ConstraintExpr))); |
| 2273 | } |
| 2274 | |
| 2275 | if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(Val: D)) { |
| 2276 | // Constructor initializers. |
| 2277 | for (auto *I : Ctor->inits()) { |
| 2278 | if (I->isWritten() || getDerived().shouldVisitImplicitCode()) |
| 2279 | TRY_TO(TraverseConstructorInitializer(I)); |
| 2280 | } |
| 2281 | } |
| 2282 | |
| 2283 | bool VisitBody = |
| 2284 | D->isThisDeclarationADefinition() && |
| 2285 | // Don't visit the function body if the function definition is generated |
| 2286 | // by clang. |
| 2287 | (!D->isDefaulted() || getDerived().shouldVisitImplicitCode()); |
| 2288 | |
| 2289 | if (const auto *MD = dyn_cast<CXXMethodDecl>(Val: D)) { |
| 2290 | if (const CXXRecordDecl *RD = MD->getParent()) { |
| 2291 | if (RD->isLambda() && |
| 2292 | declaresSameEntity(D1: RD->getLambdaCallOperator(), D2: MD)) { |
| 2293 | VisitBody = VisitBody && getDerived().shouldVisitLambdaBody(); |
| 2294 | } |
| 2295 | } |
| 2296 | } |
| 2297 | |
| 2298 | if (VisitBody) { |
| 2299 | TRY_TO(TraverseStmt(D->getBody())); |
| 2300 | // Body may contain using declarations whose shadows are parented to the |
| 2301 | // FunctionDecl itself. |
| 2302 | for (auto *Child : D->decls()) { |
| 2303 | if (isa<UsingShadowDecl>(Val: Child)) |
| 2304 | TRY_TO(TraverseDecl(Child)); |
| 2305 | } |
| 2306 | } |
| 2307 | return true; |
| 2308 | } |
| 2309 | |
| 2310 | DEF_TRAVERSE_DECL(FunctionDecl, { |
| 2311 | // We skip decls_begin/decls_end, which are already covered by |
| 2312 | // TraverseFunctionHelper(). |
| 2313 | ShouldVisitChildren = false; |
| 2314 | ReturnValue = TraverseFunctionHelper(D); |
| 2315 | }) |
| 2316 | |
| 2317 | DEF_TRAVERSE_DECL(CXXDeductionGuideDecl, { |
| 2318 | // We skip decls_begin/decls_end, which are already covered by |
| 2319 | // TraverseFunctionHelper(). |
| 2320 | ShouldVisitChildren = false; |
| 2321 | ReturnValue = TraverseFunctionHelper(D); |
| 2322 | }) |
| 2323 | |
| 2324 | DEF_TRAVERSE_DECL(CXXMethodDecl, { |
| 2325 | // We skip decls_begin/decls_end, which are already covered by |
| 2326 | // TraverseFunctionHelper(). |
| 2327 | ShouldVisitChildren = false; |
| 2328 | ReturnValue = TraverseFunctionHelper(D); |
| 2329 | }) |
| 2330 | |
| 2331 | DEF_TRAVERSE_DECL(CXXConstructorDecl, { |
| 2332 | // We skip decls_begin/decls_end, which are already covered by |
| 2333 | // TraverseFunctionHelper(). |
| 2334 | ShouldVisitChildren = false; |
| 2335 | ReturnValue = TraverseFunctionHelper(D); |
| 2336 | }) |
| 2337 | |
| 2338 | // CXXConversionDecl is the declaration of a type conversion operator. |
| 2339 | // It's not a cast expression. |
| 2340 | DEF_TRAVERSE_DECL(CXXConversionDecl, { |
| 2341 | // We skip decls_begin/decls_end, which are already covered by |
| 2342 | // TraverseFunctionHelper(). |
| 2343 | ShouldVisitChildren = false; |
| 2344 | ReturnValue = TraverseFunctionHelper(D); |
| 2345 | }) |
| 2346 | |
| 2347 | DEF_TRAVERSE_DECL(CXXDestructorDecl, { |
| 2348 | // We skip decls_begin/decls_end, which are already covered by |
| 2349 | // TraverseFunctionHelper(). |
| 2350 | ShouldVisitChildren = false; |
| 2351 | ReturnValue = TraverseFunctionHelper(D); |
| 2352 | }) |
| 2353 | |
| 2354 | template <typename Derived> |
| 2355 | bool RecursiveASTVisitor<Derived>::TraverseVarHelper(VarDecl *D) { |
| 2356 | TRY_TO(TraverseDeclaratorHelper(D)); |
| 2357 | // Default params are taken care of when we traverse the ParmVarDecl. |
| 2358 | if (!isa<ParmVarDecl>(Val: D) && |
| 2359 | (!D->isCXXForRangeDecl() || getDerived().shouldVisitImplicitCode())) |
| 2360 | TRY_TO(TraverseStmt(D->getInit())); |
| 2361 | return true; |
| 2362 | } |
| 2363 | |
| 2364 | DEF_TRAVERSE_DECL(VarDecl, { TRY_TO(TraverseVarHelper(D)); }) |
| 2365 | |
| 2366 | DEF_TRAVERSE_DECL(ImplicitParamDecl, { TRY_TO(TraverseVarHelper(D)); }) |
| 2367 | |
| 2368 | DEF_TRAVERSE_DECL(NonTypeTemplateParmDecl, { |
| 2369 | // A non-type template parameter, e.g. "S" in template<int S> class Foo ... |
| 2370 | TRY_TO(TraverseDeclaratorHelper(D)); |
| 2371 | if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) |
| 2372 | TRY_TO(TraverseTemplateArgumentLoc(D->getDefaultArgument())); |
| 2373 | }) |
| 2374 | |
| 2375 | DEF_TRAVERSE_DECL(ParmVarDecl, { |
| 2376 | TRY_TO(TraverseVarHelper(D)); |
| 2377 | |
| 2378 | if (D->hasDefaultArg() && D->hasUninstantiatedDefaultArg() && |
| 2379 | !D->hasUnparsedDefaultArg()) |
| 2380 | TRY_TO(TraverseStmt(D->getUninstantiatedDefaultArg())); |
| 2381 | |
| 2382 | if (D->hasDefaultArg() && !D->hasUninstantiatedDefaultArg() && |
| 2383 | !D->hasUnparsedDefaultArg()) |
| 2384 | TRY_TO(TraverseStmt(D->getDefaultArg())); |
| 2385 | }) |
| 2386 | |
| 2387 | DEF_TRAVERSE_DECL(RequiresExprBodyDecl, {}) |
| 2388 | |
| 2389 | DEF_TRAVERSE_DECL(ImplicitConceptSpecializationDecl, { |
| 2390 | TRY_TO(TraverseTemplateArguments(D->getTemplateArguments())); |
| 2391 | }) |
| 2392 | |
| 2393 | #undef DEF_TRAVERSE_DECL |
| 2394 | |
| 2395 | // ----------------- Stmt traversal ----------------- |
| 2396 | // |
| 2397 | // For stmts, we automate (in the DEF_TRAVERSE_STMT macro) iterating |
| 2398 | // over the children defined in children() (every stmt defines these, |
| 2399 | // though sometimes the range is empty). Each individual Traverse* |
| 2400 | // method only needs to worry about children other than those. To see |
| 2401 | // what children() does for a given class, see, e.g., |
| 2402 | // http://clang.llvm.org/doxygen/Stmt_8cpp_source.html |
| 2403 | |
| 2404 | // This macro makes available a variable S, the passed-in stmt. |
| 2405 | #define DEF_TRAVERSE_STMT(STMT, CODE) \ |
| 2406 | template <typename Derived> \ |
| 2407 | bool RecursiveASTVisitor<Derived>::Traverse##STMT( \ |
| 2408 | STMT * |
|---|