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>(*D) && !isa<ObjCMethodDecl>(*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->isSubstitutionFailure()) 250 Visit(NR->getConstraintExpr()); 251 } 252 }); 253 } 254 255 void Visit(const APValue &Value, QualType Ty) { 256 getNodeDelegate().AddChild([=] { getNodeDelegate().Visit(Value, Ty); }); 257 } 258 259 void Visit(const comments::Comment *C, const comments::FullComment *FC) { 260 getNodeDelegate().AddChild([=] { 261 getNodeDelegate().Visit(C, FC); 262 if (!C) { 263 return; 264 } 265 comments::ConstCommentVisitor<Derived, void, 266 const comments::FullComment *>::visit(C, 267 FC); 268 for (comments::Comment::child_iterator I = C->child_begin(), 269 E = C->child_end(); 270 I != E; ++I) 271 Visit(*I, FC); 272 }); 273 } 274 275 void Visit(const DynTypedNode &N) { 276 // FIXME: Improve this with a switch or a visitor pattern. 277 if (const auto *D = N.get<Decl>()) 278 Visit(D); 279 else if (const auto *S = N.get<Stmt>()) 280 Visit(S); 281 else if (const auto *QT = N.get<QualType>()) 282 Visit(*QT); 283 else if (const auto *T = N.get<Type>()) 284 Visit(T); 285 else if (const auto *C = N.get<CXXCtorInitializer>()) 286 Visit(C); 287 else if (const auto *C = N.get<OMPClause>()) 288 Visit(C); 289 else if (const auto *T = N.get<TemplateArgument>()) 290 Visit(*T); 291 } 292 293 void dumpDeclContext(const DeclContext *DC) { 294 if (!DC) 295 return; 296 297 for (const auto *D : (Deserialize ? DC->decls() : DC->noload_decls())) 298 Visit(D); 299 } 300 301 void dumpTemplateParameters(const TemplateParameterList *TPL) { 302 if (!TPL) 303 return; 304 305 for (const auto &TP : *TPL) 306 Visit(TP); 307 308 if (const Expr *RC = TPL->getRequiresClause()) 309 Visit(RC); 310 } 311 312 void 313 dumpASTTemplateArgumentListInfo(const ASTTemplateArgumentListInfo *TALI) { 314 if (!TALI) 315 return; 316 317 for (const auto &TA : TALI->arguments()) 318 dumpTemplateArgumentLoc(TA); 319 } 320 321 void dumpTemplateArgumentLoc(const TemplateArgumentLoc &A, 322 const Decl *From = nullptr, 323 const char *Label = nullptr) { 324 Visit(A.getArgument(), A.getSourceRange(), From, Label); 325 } 326 327 void dumpTemplateArgumentList(const TemplateArgumentList &TAL) { 328 for (unsigned i = 0, e = TAL.size(); i < e; ++i) 329 Visit(TAL[i]); 330 } 331 332 void dumpObjCTypeParamList(const ObjCTypeParamList *typeParams) { 333 if (!typeParams) 334 return; 335 336 for (const auto &typeParam : *typeParams) { 337 Visit(typeParam); 338 } 339 } 340 341 void VisitComplexType(const ComplexType *T) { Visit(T->getElementType()); } 342 void VisitLocInfoType(const LocInfoType *T) { 343 Visit(T->getTypeSourceInfo()->getType()); 344 } 345 void VisitPointerType(const PointerType *T) { Visit(T->getPointeeType()); } 346 void VisitBlockPointerType(const BlockPointerType *T) { 347 Visit(T->getPointeeType()); 348 } 349 void VisitReferenceType(const ReferenceType *T) { 350 Visit(T->getPointeeType()); 351 } 352 void VisitMemberPointerType(const MemberPointerType *T) { 353 Visit(T->getClass()); 354 Visit(T->getPointeeType()); 355 } 356 void VisitArrayType(const ArrayType *T) { Visit(T->getElementType()); } 357 void VisitVariableArrayType(const VariableArrayType *T) { 358 VisitArrayType(T); 359 Visit(T->getSizeExpr()); 360 } 361 void VisitDependentSizedArrayType(const DependentSizedArrayType *T) { 362 Visit(T->getElementType()); 363 Visit(T->getSizeExpr()); 364 } 365 void VisitDependentSizedExtVectorType(const DependentSizedExtVectorType *T) { 366 Visit(T->getElementType()); 367 Visit(T->getSizeExpr()); 368 } 369 void VisitVectorType(const VectorType *T) { Visit(T->getElementType()); } 370 void VisitFunctionType(const FunctionType *T) { Visit(T->getReturnType()); } 371 void VisitFunctionProtoType(const FunctionProtoType *T) { 372 VisitFunctionType(T); 373 for (const QualType &PT : T->getParamTypes()) 374 Visit(PT); 375 } 376 void VisitTypeOfExprType(const TypeOfExprType *T) { 377 Visit(T->getUnderlyingExpr()); 378 } 379 void VisitDecltypeType(const DecltypeType *T) { 380 Visit(T->getUnderlyingExpr()); 381 } 382 void VisitUnaryTransformType(const UnaryTransformType *T) { 383 Visit(T->getBaseType()); 384 } 385 void VisitAttributedType(const AttributedType *T) { 386 // FIXME: AttrKind 387 Visit(T->getModifiedType()); 388 } 389 void VisitBTFTagAttributedType(const BTFTagAttributedType *T) { 390 Visit(T->getWrappedType()); 391 } 392 void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) { 393 Visit(T->getReplacedParameter()); 394 } 395 void 396 VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T) { 397 Visit(T->getReplacedParameter()); 398 Visit(T->getArgumentPack()); 399 } 400 void VisitTemplateSpecializationType(const TemplateSpecializationType *T) { 401 for (const auto &Arg : *T) 402 Visit(Arg); 403 } 404 void VisitObjCObjectPointerType(const ObjCObjectPointerType *T) { 405 Visit(T->getPointeeType()); 406 } 407 void VisitAtomicType(const AtomicType *T) { Visit(T->getValueType()); } 408 void VisitPipeType(const PipeType *T) { Visit(T->getElementType()); } 409 void VisitAdjustedType(const AdjustedType *T) { Visit(T->getOriginalType()); } 410 void VisitPackExpansionType(const PackExpansionType *T) { 411 if (!T->isSugared()) 412 Visit(T->getPattern()); 413 } 414 // FIXME: ElaboratedType, DependentNameType, 415 // DependentTemplateSpecializationType, ObjCObjectType 416 417 void VisitTypedefDecl(const TypedefDecl *D) { Visit(D->getUnderlyingType()); } 418 419 void VisitEnumConstantDecl(const EnumConstantDecl *D) { 420 if (const Expr *Init = D->getInitExpr()) 421 Visit(Init); 422 } 423 424 void VisitFunctionDecl(const FunctionDecl *D) { 425 if (const auto *FTSI = D->getTemplateSpecializationInfo()) 426 dumpTemplateArgumentList(*FTSI->TemplateArguments); 427 428 if (D->param_begin()) 429 for (const auto *Parameter : D->parameters()) 430 Visit(Parameter); 431 432 if (const Expr *TRC = D->getTrailingRequiresClause()) 433 Visit(TRC); 434 435 if (Traversal == TK_IgnoreUnlessSpelledInSource && D->isDefaulted()) 436 return; 437 438 if (const auto *C = dyn_cast<CXXConstructorDecl>(D)) 439 for (const auto *I : C->inits()) 440 Visit(I); 441 442 if (D->doesThisDeclarationHaveABody()) 443 Visit(D->getBody()); 444 } 445 446 void VisitFieldDecl(const FieldDecl *D) { 447 if (D->isBitField()) 448 Visit(D->getBitWidth()); 449 if (Expr *Init = D->getInClassInitializer()) 450 Visit(Init); 451 } 452 453 void VisitVarDecl(const VarDecl *D) { 454 if (Traversal == TK_IgnoreUnlessSpelledInSource && D->isCXXForRangeDecl()) 455 return; 456 457 if (D->hasInit()) 458 Visit(D->getInit()); 459 } 460 461 void VisitDecompositionDecl(const DecompositionDecl *D) { 462 VisitVarDecl(D); 463 for (const auto *B : D->bindings()) 464 Visit(B); 465 } 466 467 void VisitBindingDecl(const BindingDecl *D) { 468 if (Traversal == TK_IgnoreUnlessSpelledInSource) 469 return; 470 471 if (const auto *V = D->getHoldingVar()) 472 Visit(V); 473 474 if (const auto *E = D->getBinding()) 475 Visit(E); 476 } 477 478 void VisitFileScopeAsmDecl(const FileScopeAsmDecl *D) { 479 Visit(D->getAsmString()); 480 } 481 482 void VisitCapturedDecl(const CapturedDecl *D) { Visit(D->getBody()); } 483 484 void VisitOMPThreadPrivateDecl(const OMPThreadPrivateDecl *D) { 485 for (const auto *E : D->varlists()) 486 Visit(E); 487 } 488 489 void VisitOMPDeclareReductionDecl(const OMPDeclareReductionDecl *D) { 490 Visit(D->getCombiner()); 491 if (const auto *Initializer = D->getInitializer()) 492 Visit(Initializer); 493 } 494 495 void VisitOMPDeclareMapperDecl(const OMPDeclareMapperDecl *D) { 496 for (const auto *C : D->clauselists()) 497 Visit(C); 498 } 499 500 void VisitOMPCapturedExprDecl(const OMPCapturedExprDecl *D) { 501 Visit(D->getInit()); 502 } 503 504 void VisitOMPAllocateDecl(const OMPAllocateDecl *D) { 505 for (const auto *E : D->varlists()) 506 Visit(E); 507 for (const auto *C : D->clauselists()) 508 Visit(C); 509 } 510 511 template <typename SpecializationDecl> 512 void dumpTemplateDeclSpecialization(const SpecializationDecl *D) { 513 for (const auto *RedeclWithBadType : D->redecls()) { 514 // FIXME: The redecls() range sometimes has elements of a less-specific 515 // type. (In particular, ClassTemplateSpecializationDecl::redecls() gives 516 // us TagDecls, and should give CXXRecordDecls). 517 auto *Redecl = dyn_cast<SpecializationDecl>(RedeclWithBadType); 518 if (!Redecl) { 519 // Found the injected-class-name for a class template. This will be 520 // dumped as part of its surrounding class so we don't need to dump it 521 // here. 522 assert(isa<CXXRecordDecl>(RedeclWithBadType) && 523 "expected an injected-class-name"); 524 continue; 525 } 526 Visit(Redecl); 527 } 528 } 529 530 template <typename TemplateDecl> 531 void dumpTemplateDecl(const TemplateDecl *D) { 532 dumpTemplateParameters(D->getTemplateParameters()); 533 534 Visit(D->getTemplatedDecl()); 535 536 if (Traversal == TK_AsIs) { 537 for (const auto *Child : D->specializations()) 538 dumpTemplateDeclSpecialization(Child); 539 } 540 } 541 542 void VisitTypeAliasDecl(const TypeAliasDecl *D) { 543 Visit(D->getUnderlyingType()); 544 } 545 546 void VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D) { 547 dumpTemplateParameters(D->getTemplateParameters()); 548 Visit(D->getTemplatedDecl()); 549 } 550 551 void VisitStaticAssertDecl(const StaticAssertDecl *D) { 552 Visit(D->getAssertExpr()); 553 Visit(D->getMessage()); 554 } 555 556 void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) { 557 dumpTemplateDecl(D); 558 } 559 560 void VisitClassTemplateDecl(const ClassTemplateDecl *D) { 561 dumpTemplateDecl(D); 562 } 563 564 void VisitClassTemplateSpecializationDecl( 565 const ClassTemplateSpecializationDecl *D) { 566 dumpTemplateArgumentList(D->getTemplateArgs()); 567 } 568 569 void VisitClassTemplatePartialSpecializationDecl( 570 const ClassTemplatePartialSpecializationDecl *D) { 571 VisitClassTemplateSpecializationDecl(D); 572 dumpTemplateParameters(D->getTemplateParameters()); 573 } 574 575 void VisitClassScopeFunctionSpecializationDecl( 576 const ClassScopeFunctionSpecializationDecl *D) { 577 Visit(D->getSpecialization()); 578 dumpASTTemplateArgumentListInfo(D->getTemplateArgsAsWritten()); 579 } 580 void VisitVarTemplateDecl(const VarTemplateDecl *D) { dumpTemplateDecl(D); } 581 582 void VisitBuiltinTemplateDecl(const BuiltinTemplateDecl *D) { 583 dumpTemplateParameters(D->getTemplateParameters()); 584 } 585 586 void 587 VisitVarTemplateSpecializationDecl(const VarTemplateSpecializationDecl *D) { 588 dumpTemplateArgumentList(D->getTemplateArgs()); 589 VisitVarDecl(D); 590 } 591 592 void VisitVarTemplatePartialSpecializationDecl( 593 const VarTemplatePartialSpecializationDecl *D) { 594 dumpTemplateParameters(D->getTemplateParameters()); 595 VisitVarTemplateSpecializationDecl(D); 596 } 597 598 void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) { 599 if (const auto *TC = D->getTypeConstraint()) 600 Visit(TC->getImmediatelyDeclaredConstraint()); 601 if (D->hasDefaultArgument()) 602 Visit(D->getDefaultArgument(), SourceRange(), 603 D->getDefaultArgStorage().getInheritedFrom(), 604 D->defaultArgumentWasInherited() ? "inherited from" : "previous"); 605 } 606 607 void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D) { 608 if (const auto *E = D->getPlaceholderTypeConstraint()) 609 Visit(E); 610 if (D->hasDefaultArgument()) 611 Visit(D->getDefaultArgument(), SourceRange(), 612 D->getDefaultArgStorage().getInheritedFrom(), 613 D->defaultArgumentWasInherited() ? "inherited from" : "previous"); 614 } 615 616 void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D) { 617 dumpTemplateParameters(D->getTemplateParameters()); 618 if (D->hasDefaultArgument()) 619 dumpTemplateArgumentLoc( 620 D->getDefaultArgument(), D->getDefaultArgStorage().getInheritedFrom(), 621 D->defaultArgumentWasInherited() ? "inherited from" : "previous"); 622 } 623 624 void VisitConceptDecl(const ConceptDecl *D) { 625 dumpTemplateParameters(D->getTemplateParameters()); 626 Visit(D->getConstraintExpr()); 627 } 628 629 void VisitConceptSpecializationExpr(const ConceptSpecializationExpr *CSE) { 630 if (CSE->hasExplicitTemplateArgs()) 631 for (const auto &ArgLoc : CSE->getTemplateArgsAsWritten()->arguments()) 632 dumpTemplateArgumentLoc(ArgLoc); 633 } 634 635 void VisitUsingShadowDecl(const UsingShadowDecl *D) { 636 if (auto *TD = dyn_cast<TypeDecl>(D->getUnderlyingDecl())) 637 Visit(TD->getTypeForDecl()); 638 } 639 640 void VisitFriendDecl(const FriendDecl *D) { 641 if (!D->getFriendType()) 642 Visit(D->getFriendDecl()); 643 } 644 645 void VisitObjCMethodDecl(const ObjCMethodDecl *D) { 646 if (D->isThisDeclarationADefinition()) 647 dumpDeclContext(D); 648 else 649 for (const ParmVarDecl *Parameter : D->parameters()) 650 Visit(Parameter); 651 652 if (D->hasBody()) 653 Visit(D->getBody()); 654 } 655 656 void VisitObjCCategoryDecl(const ObjCCategoryDecl *D) { 657 dumpObjCTypeParamList(D->getTypeParamList()); 658 } 659 660 void VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) { 661 dumpObjCTypeParamList(D->getTypeParamListAsWritten()); 662 } 663 664 void VisitObjCImplementationDecl(const ObjCImplementationDecl *D) { 665 for (const auto &I : D->inits()) 666 Visit(I); 667 } 668 669 void VisitBlockDecl(const BlockDecl *D) { 670 for (const auto &I : D->parameters()) 671 Visit(I); 672 673 for (const auto &I : D->captures()) 674 Visit(I); 675 Visit(D->getBody()); 676 } 677 678 void VisitDeclStmt(const DeclStmt *Node) { 679 for (const auto &D : Node->decls()) 680 Visit(D); 681 } 682 683 void VisitAttributedStmt(const AttributedStmt *Node) { 684 for (const auto *A : Node->getAttrs()) 685 Visit(A); 686 } 687 688 void VisitCXXCatchStmt(const CXXCatchStmt *Node) { 689 Visit(Node->getExceptionDecl()); 690 } 691 692 void VisitCapturedStmt(const CapturedStmt *Node) { 693 Visit(Node->getCapturedDecl()); 694 } 695 696 void VisitOMPExecutableDirective(const OMPExecutableDirective *Node) { 697 for (const auto *C : Node->clauses()) 698 Visit(C); 699 } 700 701 void VisitInitListExpr(const InitListExpr *ILE) { 702 if (auto *Filler = ILE->getArrayFiller()) { 703 Visit(Filler, "array_filler"); 704 } 705 } 706 707 void VisitBlockExpr(const BlockExpr *Node) { Visit(Node->getBlockDecl()); } 708 709 void VisitOpaqueValueExpr(const OpaqueValueExpr *Node) { 710 if (Expr *Source = Node->getSourceExpr()) 711 Visit(Source); 712 } 713 714 void VisitGenericSelectionExpr(const GenericSelectionExpr *E) { 715 Visit(E->getControllingExpr()); 716 Visit(E->getControllingExpr()->getType()); // FIXME: remove 717 718 for (const auto Assoc : E->associations()) { 719 Visit(Assoc); 720 } 721 } 722 723 void VisitRequiresExpr(const RequiresExpr *E) { 724 for (auto *D : E->getLocalParameters()) 725 Visit(D); 726 for (auto *R : E->getRequirements()) 727 Visit(R); 728 } 729 730 void VisitLambdaExpr(const LambdaExpr *Node) { 731 if (Traversal == TK_IgnoreUnlessSpelledInSource) { 732 for (unsigned I = 0, N = Node->capture_size(); I != N; ++I) { 733 const auto *C = Node->capture_begin() + I; 734 if (!C->isExplicit()) 735 continue; 736 if (Node->isInitCapture(C)) 737 Visit(C->getCapturedVar()); 738 else 739 Visit(Node->capture_init_begin()[I]); 740 } 741 dumpTemplateParameters(Node->getTemplateParameterList()); 742 for (const auto *P : Node->getCallOperator()->parameters()) 743 Visit(P); 744 Visit(Node->getBody()); 745 } else { 746 return Visit(Node->getLambdaClass()); 747 } 748 } 749 750 void VisitSizeOfPackExpr(const SizeOfPackExpr *Node) { 751 if (Node->isPartiallySubstituted()) 752 for (const auto &A : Node->getPartialArguments()) 753 Visit(A); 754 } 755 756 void VisitSubstNonTypeTemplateParmExpr(const SubstNonTypeTemplateParmExpr *E) { 757 Visit(E->getParameter()); 758 } 759 void VisitSubstNonTypeTemplateParmPackExpr( 760 const SubstNonTypeTemplateParmPackExpr *E) { 761 Visit(E->getParameterPack()); 762 Visit(E->getArgumentPack()); 763 } 764 765 void VisitObjCAtCatchStmt(const ObjCAtCatchStmt *Node) { 766 if (const VarDecl *CatchParam = Node->getCatchParamDecl()) 767 Visit(CatchParam); 768 } 769 770 void VisitCXXForRangeStmt(const CXXForRangeStmt *Node) { 771 if (Traversal == TK_IgnoreUnlessSpelledInSource) { 772 Visit(Node->getInit()); 773 Visit(Node->getLoopVariable()); 774 Visit(Node->getRangeInit()); 775 Visit(Node->getBody()); 776 } 777 } 778 779 void VisitCallExpr(const CallExpr *Node) { 780 for (const auto *Child : 781 make_filter_range(Node->children(), [this](const Stmt *Child) { 782 if (Traversal != TK_IgnoreUnlessSpelledInSource) 783 return false; 784 return !isa<CXXDefaultArgExpr>(Child); 785 })) { 786 Visit(Child); 787 } 788 } 789 790 void VisitCXXRewrittenBinaryOperator(const CXXRewrittenBinaryOperator *Node) { 791 if (Traversal == TK_IgnoreUnlessSpelledInSource) { 792 Visit(Node->getLHS()); 793 Visit(Node->getRHS()); 794 } else { 795 ConstStmtVisitor<Derived>::VisitCXXRewrittenBinaryOperator(Node); 796 } 797 } 798 799 void VisitExpressionTemplateArgument(const TemplateArgument &TA) { 800 Visit(TA.getAsExpr()); 801 } 802 803 void VisitTypeTemplateArgument(const TemplateArgument &TA) { 804 Visit(TA.getAsType()); 805 } 806 807 void VisitPackTemplateArgument(const TemplateArgument &TA) { 808 for (const auto &TArg : TA.pack_elements()) 809 Visit(TArg); 810 } 811 812 // Implements Visit methods for Attrs. 813 #include "clang/AST/AttrNodeTraverse.inc" 814 }; 815 816 } // namespace clang 817 818 #endif // LLVM_CLANG_AST_ASTNODETRAVERSER_H 819