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