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