1 //===--- ASTNodeTraverser.h - Traversal of AST nodes ----------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file implements the AST traversal facilities. Other users 10 // of this class may make use of the same traversal logic by inheriting it, 11 // similar to RecursiveASTVisitor. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #ifndef LLVM_CLANG_AST_ASTNODETRAVERSER_H 16 #define LLVM_CLANG_AST_ASTNODETRAVERSER_H 17 18 #include "clang/AST/ASTTypeTraits.h" 19 #include "clang/AST/AttrVisitor.h" 20 #include "clang/AST/CommentVisitor.h" 21 #include "clang/AST/DeclVisitor.h" 22 #include "clang/AST/LocInfoType.h" 23 #include "clang/AST/StmtVisitor.h" 24 #include "clang/AST/TemplateArgumentVisitor.h" 25 #include "clang/AST/Type.h" 26 #include "clang/AST/TypeVisitor.h" 27 28 namespace clang { 29 30 class APValue; 31 32 /** 33 34 ASTNodeTraverser traverses the Clang AST for dumping purposes. 35 36 The `Derived::doGetNodeDelegate()` method is required to be an accessible member 37 which returns a reference of type `NodeDelegateType &` which implements the 38 following interface: 39 40 struct { 41 template <typename Fn> void AddChild(Fn DoAddChild); 42 template <typename Fn> void AddChild(StringRef Label, Fn DoAddChild); 43 44 void Visit(const comments::Comment *C, const comments::FullComment *FC); 45 void Visit(const Attr *A); 46 void Visit(const TemplateArgument &TA, SourceRange R = {}, 47 const Decl *From = nullptr, StringRef Label = {}); 48 void Visit(const Stmt *Node); 49 void Visit(const Type *T); 50 void Visit(QualType T); 51 void Visit(const Decl *D); 52 void Visit(const CXXCtorInitializer *Init); 53 void Visit(const OMPClause *C); 54 void Visit(const BlockDecl::Capture &C); 55 void Visit(const GenericSelectionExpr::ConstAssociation &A); 56 void Visit(const concepts::Requirement *R); 57 void Visit(const APValue &Value, QualType Ty); 58 }; 59 */ 60 template <typename Derived, typename NodeDelegateType> 61 class ASTNodeTraverser 62 : public ConstDeclVisitor<Derived>, 63 public ConstStmtVisitor<Derived>, 64 public comments::ConstCommentVisitor<Derived, void, 65 const comments::FullComment *>, 66 public TypeVisitor<Derived>, 67 public ConstAttrVisitor<Derived>, 68 public ConstTemplateArgumentVisitor<Derived> { 69 70 /// Indicates whether we should trigger deserialization of nodes that had 71 /// not already been loaded. 72 bool Deserialize = false; 73 74 TraversalKind Traversal = TraversalKind::TK_AsIs; 75 76 NodeDelegateType &getNodeDelegate() { 77 return getDerived().doGetNodeDelegate(); 78 } 79 Derived &getDerived() { return *static_cast<Derived *>(this); } 80 81 public: 82 void setDeserialize(bool D) { Deserialize = D; } 83 bool getDeserialize() const { return Deserialize; } 84 85 void SetTraversalKind(TraversalKind TK) { Traversal = TK; } 86 TraversalKind GetTraversalKind() const { return Traversal; } 87 88 void Visit(const Decl *D) { 89 if (Traversal == TK_IgnoreUnlessSpelledInSource && D->isImplicit()) 90 return; 91 92 getNodeDelegate().AddChild([=] { 93 getNodeDelegate().Visit(D); 94 if (!D) 95 return; 96 97 ConstDeclVisitor<Derived>::Visit(D); 98 99 for (const auto &A : D->attrs()) 100 Visit(A); 101 102 if (const comments::FullComment *Comment = 103 D->getASTContext().getLocalCommentForDeclUncached(D)) 104 Visit(Comment, Comment); 105 106 // Decls within functions are visited by the body. 107 if (!isa<FunctionDecl, ObjCMethodDecl, BlockDecl>(*D)) { 108 if (Traversal != TK_AsIs) { 109 if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(D)) { 110 auto SK = CTSD->getSpecializationKind(); 111 if (SK == TSK_ExplicitInstantiationDeclaration || 112 SK == TSK_ExplicitInstantiationDefinition) 113 return; 114 } 115 } 116 if (const auto *DC = dyn_cast<DeclContext>(D)) 117 dumpDeclContext(DC); 118 } 119 }); 120 } 121 122 void Visit(const Stmt *Node, StringRef Label = {}) { 123 getNodeDelegate().AddChild(Label, [=] { 124 const Stmt *S = Node; 125 126 if (auto *E = dyn_cast_or_null<Expr>(S)) { 127 switch (Traversal) { 128 case TK_AsIs: 129 break; 130 case TK_IgnoreUnlessSpelledInSource: 131 S = E->IgnoreUnlessSpelledInSource(); 132 break; 133 } 134 } 135 136 getNodeDelegate().Visit(S); 137 138 if (!S) { 139 return; 140 } 141 142 ConstStmtVisitor<Derived>::Visit(S); 143 144 // Some statements have custom mechanisms for dumping their children. 145 if (isa<DeclStmt>(S) || isa<GenericSelectionExpr>(S) || 146 isa<RequiresExpr>(S)) 147 return; 148 149 if (Traversal == TK_IgnoreUnlessSpelledInSource && 150 isa<LambdaExpr, CXXForRangeStmt, CallExpr, 151 CXXRewrittenBinaryOperator>(S)) 152 return; 153 154 for (const Stmt *SubStmt : S->children()) 155 Visit(SubStmt); 156 }); 157 } 158 159 void Visit(QualType T) { 160 SplitQualType SQT = T.split(); 161 if (!SQT.Quals.hasQualifiers()) 162 return Visit(SQT.Ty); 163 164 getNodeDelegate().AddChild([=] { 165 getNodeDelegate().Visit(T); 166 Visit(T.split().Ty); 167 }); 168 } 169 170 void Visit(const Type *T) { 171 getNodeDelegate().AddChild([=] { 172 getNodeDelegate().Visit(T); 173 if (!T) 174 return; 175 TypeVisitor<Derived>::Visit(T); 176 177 QualType SingleStepDesugar = 178 T->getLocallyUnqualifiedSingleStepDesugaredType(); 179 if (SingleStepDesugar != QualType(T, 0)) 180 Visit(SingleStepDesugar); 181 }); 182 } 183 184 void Visit(const Attr *A) { 185 getNodeDelegate().AddChild([=] { 186 getNodeDelegate().Visit(A); 187 ConstAttrVisitor<Derived>::Visit(A); 188 }); 189 } 190 191 void Visit(const CXXCtorInitializer *Init) { 192 if (Traversal == TK_IgnoreUnlessSpelledInSource && !Init->isWritten()) 193 return; 194 getNodeDelegate().AddChild([=] { 195 getNodeDelegate().Visit(Init); 196 Visit(Init->getInit()); 197 }); 198 } 199 200 void Visit(const TemplateArgument &A, SourceRange R = {}, 201 const Decl *From = nullptr, const char *Label = nullptr) { 202 getNodeDelegate().AddChild([=] { 203 getNodeDelegate().Visit(A, R, From, Label); 204 ConstTemplateArgumentVisitor<Derived>::Visit(A); 205 }); 206 } 207 208 void Visit(const BlockDecl::Capture &C) { 209 getNodeDelegate().AddChild([=] { 210 getNodeDelegate().Visit(C); 211 if (C.hasCopyExpr()) 212 Visit(C.getCopyExpr()); 213 }); 214 } 215 216 void Visit(const OMPClause *C) { 217 getNodeDelegate().AddChild([=] { 218 getNodeDelegate().Visit(C); 219 for (const auto *S : C->children()) 220 Visit(S); 221 }); 222 } 223 224 void Visit(const GenericSelectionExpr::ConstAssociation &A) { 225 getNodeDelegate().AddChild([=] { 226 getNodeDelegate().Visit(A); 227 if (const TypeSourceInfo *TSI = A.getTypeSourceInfo()) 228 Visit(TSI->getType()); 229 Visit(A.getAssociationExpr()); 230 }); 231 } 232 233 void Visit(const concepts::Requirement *R) { 234 getNodeDelegate().AddChild([=] { 235 getNodeDelegate().Visit(R); 236 if (!R) 237 return; 238 if (auto *TR = dyn_cast<concepts::TypeRequirement>(R)) { 239 if (!TR->isSubstitutionFailure()) 240 Visit(TR->getType()->getType().getTypePtr()); 241 } else if (auto *ER = dyn_cast<concepts::ExprRequirement>(R)) { 242 if (!ER->isExprSubstitutionFailure()) 243 Visit(ER->getExpr()); 244 if (!ER->getReturnTypeRequirement().isEmpty()) 245 Visit(ER->getReturnTypeRequirement() 246 .getTypeConstraint() 247 ->getImmediatelyDeclaredConstraint()); 248 } else if (auto *NR = dyn_cast<concepts::NestedRequirement>(R)) { 249 if (!NR->hasInvalidConstraint()) 250 Visit(NR->getConstraintExpr()); 251 } 252 }); 253 } 254 255 void Visit(const ConceptReference *R) { 256 getNodeDelegate().AddChild([=] { getNodeDelegate().Visit(R); }); 257 } 258 259 void Visit(const APValue &Value, QualType Ty) { 260 getNodeDelegate().AddChild([=] { getNodeDelegate().Visit(Value, Ty); }); 261 } 262 263 void Visit(const comments::Comment *C, const comments::FullComment *FC) { 264 getNodeDelegate().AddChild([=] { 265 getNodeDelegate().Visit(C, FC); 266 if (!C) { 267 return; 268 } 269 comments::ConstCommentVisitor<Derived, void, 270 const comments::FullComment *>::visit(C, 271 FC); 272 for (comments::Comment::child_iterator I = C->child_begin(), 273 E = C->child_end(); 274 I != E; ++I) 275 Visit(*I, FC); 276 }); 277 } 278 279 void Visit(const DynTypedNode &N) { 280 // FIXME: Improve this with a switch or a visitor pattern. 281 if (const auto *D = N.get<Decl>()) 282 Visit(D); 283 else if (const auto *S = N.get<Stmt>()) 284 Visit(S); 285 else if (const auto *QT = N.get<QualType>()) 286 Visit(*QT); 287 else if (const auto *T = N.get<Type>()) 288 Visit(T); 289 else if (const auto *C = N.get<CXXCtorInitializer>()) 290 Visit(C); 291 else if (const auto *C = N.get<OMPClause>()) 292 Visit(C); 293 else if (const auto *T = N.get<TemplateArgument>()) 294 Visit(*T); 295 else if (const auto *CR = N.get<ConceptReference>()) 296 Visit(CR); 297 } 298 299 void dumpDeclContext(const DeclContext *DC) { 300 if (!DC) 301 return; 302 303 for (const auto *D : (Deserialize ? DC->decls() : DC->noload_decls())) 304 Visit(D); 305 } 306 307 void dumpTemplateParameters(const TemplateParameterList *TPL) { 308 if (!TPL) 309 return; 310 311 for (const auto &TP : *TPL) 312 Visit(TP); 313 314 if (const Expr *RC = TPL->getRequiresClause()) 315 Visit(RC); 316 } 317 318 void 319 dumpASTTemplateArgumentListInfo(const ASTTemplateArgumentListInfo *TALI) { 320 if (!TALI) 321 return; 322 323 for (const auto &TA : TALI->arguments()) 324 dumpTemplateArgumentLoc(TA); 325 } 326 327 void dumpTemplateArgumentLoc(const TemplateArgumentLoc &A, 328 const Decl *From = nullptr, 329 const char *Label = nullptr) { 330 Visit(A.getArgument(), A.getSourceRange(), From, Label); 331 } 332 333 void dumpTemplateArgumentList(const TemplateArgumentList &TAL) { 334 for (unsigned i = 0, e = TAL.size(); i < e; ++i) 335 Visit(TAL[i]); 336 } 337 338 void dumpObjCTypeParamList(const ObjCTypeParamList *typeParams) { 339 if (!typeParams) 340 return; 341 342 for (const auto &typeParam : *typeParams) { 343 Visit(typeParam); 344 } 345 } 346 347 void VisitComplexType(const ComplexType *T) { Visit(T->getElementType()); } 348 void VisitLocInfoType(const LocInfoType *T) { 349 Visit(T->getTypeSourceInfo()->getType()); 350 } 351 void VisitPointerType(const PointerType *T) { Visit(T->getPointeeType()); } 352 void VisitBlockPointerType(const BlockPointerType *T) { 353 Visit(T->getPointeeType()); 354 } 355 void VisitReferenceType(const ReferenceType *T) { 356 Visit(T->getPointeeType()); 357 } 358 void VisitMemberPointerType(const MemberPointerType *T) { 359 Visit(T->getClass()); 360 Visit(T->getPointeeType()); 361 } 362 void VisitArrayType(const ArrayType *T) { Visit(T->getElementType()); } 363 void VisitVariableArrayType(const VariableArrayType *T) { 364 VisitArrayType(T); 365 Visit(T->getSizeExpr()); 366 } 367 void VisitDependentSizedArrayType(const DependentSizedArrayType *T) { 368 Visit(T->getElementType()); 369 Visit(T->getSizeExpr()); 370 } 371 void VisitDependentSizedExtVectorType(const DependentSizedExtVectorType *T) { 372 Visit(T->getElementType()); 373 Visit(T->getSizeExpr()); 374 } 375 void VisitVectorType(const VectorType *T) { Visit(T->getElementType()); } 376 void VisitFunctionType(const FunctionType *T) { Visit(T->getReturnType()); } 377 void VisitFunctionProtoType(const FunctionProtoType *T) { 378 VisitFunctionType(T); 379 for (const QualType &PT : T->getParamTypes()) 380 Visit(PT); 381 } 382 void VisitTypeOfExprType(const TypeOfExprType *T) { 383 Visit(T->getUnderlyingExpr()); 384 } 385 void VisitDecltypeType(const DecltypeType *T) { 386 Visit(T->getUnderlyingExpr()); 387 } 388 void VisitUnaryTransformType(const UnaryTransformType *T) { 389 Visit(T->getBaseType()); 390 } 391 void VisitAttributedType(const AttributedType *T) { 392 // FIXME: AttrKind 393 if (T->getModifiedType() != T->getEquivalentType()) 394 Visit(T->getModifiedType()); 395 } 396 void VisitBTFTagAttributedType(const BTFTagAttributedType *T) { 397 Visit(T->getWrappedType()); 398 } 399 void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *) {} 400 void 401 VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T) { 402 Visit(T->getArgumentPack()); 403 } 404 void VisitTemplateSpecializationType(const TemplateSpecializationType *T) { 405 for (const auto &Arg : T->template_arguments()) 406 Visit(Arg); 407 } 408 void VisitObjCObjectPointerType(const ObjCObjectPointerType *T) { 409 Visit(T->getPointeeType()); 410 } 411 void VisitAtomicType(const AtomicType *T) { Visit(T->getValueType()); } 412 void VisitPipeType(const PipeType *T) { Visit(T->getElementType()); } 413 void VisitAdjustedType(const AdjustedType *T) { Visit(T->getOriginalType()); } 414 void VisitPackExpansionType(const PackExpansionType *T) { 415 if (!T->isSugared()) 416 Visit(T->getPattern()); 417 } 418 // FIXME: ElaboratedType, DependentNameType, 419 // DependentTemplateSpecializationType, ObjCObjectType 420 421 void VisitTypedefDecl(const TypedefDecl *D) { Visit(D->getUnderlyingType()); } 422 423 void VisitEnumConstantDecl(const EnumConstantDecl *D) { 424 if (const Expr *Init = D->getInitExpr()) 425 Visit(Init); 426 } 427 428 void VisitFunctionDecl(const FunctionDecl *D) { 429 if (FunctionTemplateSpecializationInfo *FTSI = 430 D->getTemplateSpecializationInfo()) 431 dumpTemplateArgumentList(*FTSI->TemplateArguments); 432 else if (DependentFunctionTemplateSpecializationInfo *DFTSI = 433 D->getDependentSpecializationInfo()) 434 dumpASTTemplateArgumentListInfo(DFTSI->TemplateArgumentsAsWritten); 435 436 if (D->param_begin()) 437 for (const auto *Parameter : D->parameters()) 438 Visit(Parameter); 439 440 if (const Expr *TRC = D->getTrailingRequiresClause()) 441 Visit(TRC); 442 443 if (Traversal == TK_IgnoreUnlessSpelledInSource && D->isDefaulted()) 444 return; 445 446 if (const auto *C = dyn_cast<CXXConstructorDecl>(D)) 447 for (const auto *I : C->inits()) 448 Visit(I); 449 450 if (D->doesThisDeclarationHaveABody()) 451 Visit(D->getBody()); 452 } 453 454 void VisitFieldDecl(const FieldDecl *D) { 455 if (D->isBitField()) 456 Visit(D->getBitWidth()); 457 if (Expr *Init = D->getInClassInitializer()) 458 Visit(Init); 459 } 460 461 void VisitVarDecl(const VarDecl *D) { 462 if (Traversal == TK_IgnoreUnlessSpelledInSource && D->isCXXForRangeDecl()) 463 return; 464 465 if (D->hasInit()) 466 Visit(D->getInit()); 467 } 468 469 void VisitDecompositionDecl(const DecompositionDecl *D) { 470 VisitVarDecl(D); 471 for (const auto *B : D->bindings()) 472 Visit(B); 473 } 474 475 void VisitBindingDecl(const BindingDecl *D) { 476 if (Traversal == TK_IgnoreUnlessSpelledInSource) 477 return; 478 479 if (const auto *V = D->getHoldingVar()) 480 Visit(V); 481 482 if (const auto *E = D->getBinding()) 483 Visit(E); 484 } 485 486 void VisitFileScopeAsmDecl(const FileScopeAsmDecl *D) { 487 Visit(D->getAsmString()); 488 } 489 490 void VisitTopLevelStmtDecl(const TopLevelStmtDecl *D) { Visit(D->getStmt()); } 491 492 void VisitCapturedDecl(const CapturedDecl *D) { Visit(D->getBody()); } 493 494 void VisitOMPThreadPrivateDecl(const OMPThreadPrivateDecl *D) { 495 for (const auto *E : D->varlists()) 496 Visit(E); 497 } 498 499 void VisitOMPDeclareReductionDecl(const OMPDeclareReductionDecl *D) { 500 Visit(D->getCombiner()); 501 if (const auto *Initializer = D->getInitializer()) 502 Visit(Initializer); 503 } 504 505 void VisitOMPDeclareMapperDecl(const OMPDeclareMapperDecl *D) { 506 for (const auto *C : D->clauselists()) 507 Visit(C); 508 } 509 510 void VisitOMPCapturedExprDecl(const OMPCapturedExprDecl *D) { 511 Visit(D->getInit()); 512 } 513 514 void VisitOMPAllocateDecl(const OMPAllocateDecl *D) { 515 for (const auto *E : D->varlists()) 516 Visit(E); 517 for (const auto *C : D->clauselists()) 518 Visit(C); 519 } 520 521 template <typename SpecializationDecl> 522 void dumpTemplateDeclSpecialization(const SpecializationDecl *D) { 523 for (const auto *RedeclWithBadType : D->redecls()) { 524 // FIXME: The redecls() range sometimes has elements of a less-specific 525 // type. (In particular, ClassTemplateSpecializationDecl::redecls() gives 526 // us TagDecls, and should give CXXRecordDecls). 527 auto *Redecl = dyn_cast<SpecializationDecl>(RedeclWithBadType); 528 if (!Redecl) { 529 // Found the injected-class-name for a class template. This will be 530 // dumped as part of its surrounding class so we don't need to dump it 531 // here. 532 assert(isa<CXXRecordDecl>(RedeclWithBadType) && 533 "expected an injected-class-name"); 534 continue; 535 } 536 Visit(Redecl); 537 } 538 } 539 540 template <typename TemplateDecl> 541 void dumpTemplateDecl(const TemplateDecl *D) { 542 dumpTemplateParameters(D->getTemplateParameters()); 543 544 Visit(D->getTemplatedDecl()); 545 546 if (Traversal == TK_AsIs) { 547 for (const auto *Child : D->specializations()) 548 dumpTemplateDeclSpecialization(Child); 549 } 550 } 551 552 void VisitTypeAliasDecl(const TypeAliasDecl *D) { 553 Visit(D->getUnderlyingType()); 554 } 555 556 void VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D) { 557 dumpTemplateParameters(D->getTemplateParameters()); 558 Visit(D->getTemplatedDecl()); 559 } 560 561 void VisitStaticAssertDecl(const StaticAssertDecl *D) { 562 Visit(D->getAssertExpr()); 563 Visit(D->getMessage()); 564 } 565 566 void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) { 567 dumpTemplateDecl(D); 568 } 569 570 void VisitClassTemplateDecl(const ClassTemplateDecl *D) { 571 dumpTemplateDecl(D); 572 } 573 574 void VisitClassTemplateSpecializationDecl( 575 const ClassTemplateSpecializationDecl *D) { 576 dumpTemplateArgumentList(D->getTemplateArgs()); 577 } 578 579 void VisitClassTemplatePartialSpecializationDecl( 580 const ClassTemplatePartialSpecializationDecl *D) { 581 VisitClassTemplateSpecializationDecl(D); 582 dumpTemplateParameters(D->getTemplateParameters()); 583 } 584 585 void VisitVarTemplateDecl(const VarTemplateDecl *D) { dumpTemplateDecl(D); } 586 587 void VisitBuiltinTemplateDecl(const BuiltinTemplateDecl *D) { 588 dumpTemplateParameters(D->getTemplateParameters()); 589 } 590 591 void 592 VisitVarTemplateSpecializationDecl(const VarTemplateSpecializationDecl *D) { 593 dumpTemplateArgumentList(D->getTemplateArgs()); 594 VisitVarDecl(D); 595 } 596 597 void VisitVarTemplatePartialSpecializationDecl( 598 const VarTemplatePartialSpecializationDecl *D) { 599 dumpTemplateParameters(D->getTemplateParameters()); 600 VisitVarTemplateSpecializationDecl(D); 601 } 602 603 void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) { 604 if (const auto *TC = D->getTypeConstraint()) 605 Visit(TC->getImmediatelyDeclaredConstraint()); 606 if (D->hasDefaultArgument()) 607 Visit(D->getDefaultArgument(), SourceRange(), 608 D->getDefaultArgStorage().getInheritedFrom(), 609 D->defaultArgumentWasInherited() ? "inherited from" : "previous"); 610 } 611 612 void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D) { 613 if (const auto *E = D->getPlaceholderTypeConstraint()) 614 Visit(E); 615 if (D->hasDefaultArgument()) 616 Visit(D->getDefaultArgument(), SourceRange(), 617 D->getDefaultArgStorage().getInheritedFrom(), 618 D->defaultArgumentWasInherited() ? "inherited from" : "previous"); 619 } 620 621 void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D) { 622 dumpTemplateParameters(D->getTemplateParameters()); 623 if (D->hasDefaultArgument()) 624 dumpTemplateArgumentLoc( 625 D->getDefaultArgument(), D->getDefaultArgStorage().getInheritedFrom(), 626 D->defaultArgumentWasInherited() ? "inherited from" : "previous"); 627 } 628 629 void VisitConceptDecl(const ConceptDecl *D) { 630 dumpTemplateParameters(D->getTemplateParameters()); 631 Visit(D->getConstraintExpr()); 632 } 633 634 void VisitImplicitConceptSpecializationDecl( 635 const ImplicitConceptSpecializationDecl *CSD) { 636 for (const TemplateArgument &Arg : CSD->getTemplateArguments()) 637 Visit(Arg); 638 } 639 640 void VisitConceptSpecializationExpr(const ConceptSpecializationExpr *CSE) { 641 Visit(CSE->getSpecializationDecl()); 642 if (CSE->hasExplicitTemplateArgs()) 643 for (const auto &ArgLoc : CSE->getTemplateArgsAsWritten()->arguments()) 644 dumpTemplateArgumentLoc(ArgLoc); 645 } 646 647 void VisitUsingShadowDecl(const UsingShadowDecl *D) { 648 if (auto *TD = dyn_cast<TypeDecl>(D->getUnderlyingDecl())) 649 Visit(TD->getTypeForDecl()); 650 } 651 652 void VisitFriendDecl(const FriendDecl *D) { 653 if (D->getFriendType()) { 654 // Traverse any CXXRecordDecl owned by this type, since 655 // it will not be in the parent context: 656 if (auto *ET = D->getFriendType()->getType()->getAs<ElaboratedType>()) 657 if (auto *TD = ET->getOwnedTagDecl()) 658 Visit(TD); 659 } else { 660 Visit(D->getFriendDecl()); 661 } 662 } 663 664 void VisitObjCMethodDecl(const ObjCMethodDecl *D) { 665 if (D->isThisDeclarationADefinition()) 666 dumpDeclContext(D); 667 else 668 for (const ParmVarDecl *Parameter : D->parameters()) 669 Visit(Parameter); 670 671 if (D->hasBody()) 672 Visit(D->getBody()); 673 } 674 675 void VisitObjCCategoryDecl(const ObjCCategoryDecl *D) { 676 dumpObjCTypeParamList(D->getTypeParamList()); 677 } 678 679 void VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) { 680 dumpObjCTypeParamList(D->getTypeParamListAsWritten()); 681 } 682 683 void VisitObjCImplementationDecl(const ObjCImplementationDecl *D) { 684 for (const auto &I : D->inits()) 685 Visit(I); 686 } 687 688 void VisitBlockDecl(const BlockDecl *D) { 689 for (const auto &I : D->parameters()) 690 Visit(I); 691 692 for (const auto &I : D->captures()) 693 Visit(I); 694 Visit(D->getBody()); 695 } 696 697 void VisitDeclStmt(const DeclStmt *Node) { 698 for (const auto &D : Node->decls()) 699 Visit(D); 700 } 701 702 void VisitAttributedStmt(const AttributedStmt *Node) { 703 for (const auto *A : Node->getAttrs()) 704 Visit(A); 705 } 706 707 void VisitCXXCatchStmt(const CXXCatchStmt *Node) { 708 Visit(Node->getExceptionDecl()); 709 } 710 711 void VisitCapturedStmt(const CapturedStmt *Node) { 712 Visit(Node->getCapturedDecl()); 713 } 714 715 void VisitOMPExecutableDirective(const OMPExecutableDirective *Node) { 716 for (const auto *C : Node->clauses()) 717 Visit(C); 718 } 719 720 void VisitInitListExpr(const InitListExpr *ILE) { 721 if (auto *Filler = ILE->getArrayFiller()) { 722 Visit(Filler, "array_filler"); 723 } 724 } 725 726 void VisitCXXParenListInitExpr(const CXXParenListInitExpr *PLIE) { 727 if (auto *Filler = PLIE->getArrayFiller()) { 728 Visit(Filler, "array_filler"); 729 } 730 } 731 732 void VisitBlockExpr(const BlockExpr *Node) { Visit(Node->getBlockDecl()); } 733 734 void VisitOpaqueValueExpr(const OpaqueValueExpr *Node) { 735 if (Expr *Source = Node->getSourceExpr()) 736 Visit(Source); 737 } 738 739 void VisitGenericSelectionExpr(const GenericSelectionExpr *E) { 740 if (E->isExprPredicate()) { 741 Visit(E->getControllingExpr()); 742 Visit(E->getControllingExpr()->getType()); // FIXME: remove 743 } else 744 Visit(E->getControllingType()->getType()); 745 746 for (const auto Assoc : E->associations()) { 747 Visit(Assoc); 748 } 749 } 750 751 void VisitRequiresExpr(const RequiresExpr *E) { 752 for (auto *D : E->getLocalParameters()) 753 Visit(D); 754 for (auto *R : E->getRequirements()) 755 Visit(R); 756 } 757 758 void VisitLambdaExpr(const LambdaExpr *Node) { 759 if (Traversal == TK_IgnoreUnlessSpelledInSource) { 760 for (unsigned I = 0, N = Node->capture_size(); I != N; ++I) { 761 const auto *C = Node->capture_begin() + I; 762 if (!C->isExplicit()) 763 continue; 764 if (Node->isInitCapture(C)) 765 Visit(C->getCapturedVar()); 766 else 767 Visit(Node->capture_init_begin()[I]); 768 } 769 dumpTemplateParameters(Node->getTemplateParameterList()); 770 for (const auto *P : Node->getCallOperator()->parameters()) 771 Visit(P); 772 Visit(Node->getBody()); 773 } else { 774 return Visit(Node->getLambdaClass()); 775 } 776 } 777 778 void VisitSizeOfPackExpr(const SizeOfPackExpr *Node) { 779 if (Node->isPartiallySubstituted()) 780 for (const auto &A : Node->getPartialArguments()) 781 Visit(A); 782 } 783 784 void VisitSubstNonTypeTemplateParmExpr(const SubstNonTypeTemplateParmExpr *E) { 785 Visit(E->getParameter()); 786 } 787 void VisitSubstNonTypeTemplateParmPackExpr( 788 const SubstNonTypeTemplateParmPackExpr *E) { 789 Visit(E->getParameterPack()); 790 Visit(E->getArgumentPack()); 791 } 792 793 void VisitObjCAtCatchStmt(const ObjCAtCatchStmt *Node) { 794 if (const VarDecl *CatchParam = Node->getCatchParamDecl()) 795 Visit(CatchParam); 796 } 797 798 void VisitCXXForRangeStmt(const CXXForRangeStmt *Node) { 799 if (Traversal == TK_IgnoreUnlessSpelledInSource) { 800 Visit(Node->getInit()); 801 Visit(Node->getLoopVariable()); 802 Visit(Node->getRangeInit()); 803 Visit(Node->getBody()); 804 } 805 } 806 807 void VisitCallExpr(const CallExpr *Node) { 808 for (const auto *Child : 809 make_filter_range(Node->children(), [this](const Stmt *Child) { 810 if (Traversal != TK_IgnoreUnlessSpelledInSource) 811 return false; 812 return !isa<CXXDefaultArgExpr>(Child); 813 })) { 814 Visit(Child); 815 } 816 } 817 818 void VisitCXXRewrittenBinaryOperator(const CXXRewrittenBinaryOperator *Node) { 819 if (Traversal == TK_IgnoreUnlessSpelledInSource) { 820 Visit(Node->getLHS()); 821 Visit(Node->getRHS()); 822 } else { 823 ConstStmtVisitor<Derived>::VisitCXXRewrittenBinaryOperator(Node); 824 } 825 } 826 827 void VisitExpressionTemplateArgument(const TemplateArgument &TA) { 828 Visit(TA.getAsExpr()); 829 } 830 831 void VisitTypeTemplateArgument(const TemplateArgument &TA) { 832 Visit(TA.getAsType()); 833 } 834 835 void VisitPackTemplateArgument(const TemplateArgument &TA) { 836 for (const auto &TArg : TA.pack_elements()) 837 Visit(TArg); 838 } 839 840 // Implements Visit methods for Attrs. 841 #include "clang/AST/AttrNodeTraverse.inc" 842 }; 843 844 } // namespace clang 845 846 #endif // LLVM_CLANG_AST_ASTNODETRAVERSER_H 847