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 getNodeDelegate()76 NodeDelegateType &getNodeDelegate() { 77 return getDerived().doGetNodeDelegate(); 78 } getDerived()79 Derived &getDerived() { return *static_cast<Derived *>(this); } 80 81 public: setDeserialize(bool D)82 void setDeserialize(bool D) { Deserialize = D; } getDeserialize()83 bool getDeserialize() const { return Deserialize; } 84 SetTraversalKind(TraversalKind TK)85 void SetTraversalKind(TraversalKind TK) { Traversal = TK; } GetTraversalKind()86 TraversalKind GetTraversalKind() const { return Traversal; } 87 Visit(const Decl * D)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 Visit(QualType T)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 Visit(const Type * T)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 Visit(const Attr * A)184 void Visit(const Attr *A) { 185 getNodeDelegate().AddChild([=] { 186 getNodeDelegate().Visit(A); 187 ConstAttrVisitor<Derived>::Visit(A); 188 }); 189 } 190 Visit(const CXXCtorInitializer * Init)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 Visit(const BlockDecl::Capture & C)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 Visit(const OMPClause * C)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 Visit(const GenericSelectionExpr::ConstAssociation & A)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 Visit(const concepts::Requirement * R)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 Visit(const ConceptReference * R)255 void Visit(const ConceptReference *R) { 256 getNodeDelegate().AddChild([=] { getNodeDelegate().Visit(R); }); 257 } 258 Visit(const APValue & Value,QualType Ty)259 void Visit(const APValue &Value, QualType Ty) { 260 getNodeDelegate().AddChild([=] { getNodeDelegate().Visit(Value, Ty); }); 261 } 262 Visit(const comments::Comment * C,const comments::FullComment * FC)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 Visit(const DynTypedNode & N)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 dumpDeclContext(const DeclContext * DC)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 dumpTemplateParameters(const TemplateParameterList * TPL)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 dumpASTTemplateArgumentListInfo(const ASTTemplateArgumentListInfo * TALI)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 dumpTemplateArgumentList(const TemplateArgumentList & TAL)333 void dumpTemplateArgumentList(const TemplateArgumentList &TAL) { 334 for (unsigned i = 0, e = TAL.size(); i < e; ++i) 335 Visit(TAL[i]); 336 } 337 dumpObjCTypeParamList(const ObjCTypeParamList * typeParams)338 void dumpObjCTypeParamList(const ObjCTypeParamList *typeParams) { 339 if (!typeParams) 340 return; 341 342 for (const auto &typeParam : *typeParams) { 343 Visit(typeParam); 344 } 345 } 346 VisitComplexType(const ComplexType * T)347 void VisitComplexType(const ComplexType *T) { Visit(T->getElementType()); } VisitLocInfoType(const LocInfoType * T)348 void VisitLocInfoType(const LocInfoType *T) { 349 Visit(T->getTypeSourceInfo()->getType()); 350 } VisitPointerType(const PointerType * T)351 void VisitPointerType(const PointerType *T) { Visit(T->getPointeeType()); } VisitBlockPointerType(const BlockPointerType * T)352 void VisitBlockPointerType(const BlockPointerType *T) { 353 Visit(T->getPointeeType()); 354 } VisitReferenceType(const ReferenceType * T)355 void VisitReferenceType(const ReferenceType *T) { 356 Visit(T->getPointeeType()); 357 } VisitMemberPointerType(const MemberPointerType * T)358 void VisitMemberPointerType(const MemberPointerType *T) { 359 Visit(T->getClass()); 360 Visit(T->getPointeeType()); 361 } VisitArrayType(const ArrayType * T)362 void VisitArrayType(const ArrayType *T) { Visit(T->getElementType()); } VisitVariableArrayType(const VariableArrayType * T)363 void VisitVariableArrayType(const VariableArrayType *T) { 364 VisitArrayType(T); 365 Visit(T->getSizeExpr()); 366 } VisitDependentSizedArrayType(const DependentSizedArrayType * T)367 void VisitDependentSizedArrayType(const DependentSizedArrayType *T) { 368 Visit(T->getElementType()); 369 Visit(T->getSizeExpr()); 370 } VisitDependentSizedExtVectorType(const DependentSizedExtVectorType * T)371 void VisitDependentSizedExtVectorType(const DependentSizedExtVectorType *T) { 372 Visit(T->getElementType()); 373 Visit(T->getSizeExpr()); 374 } VisitVectorType(const VectorType * T)375 void VisitVectorType(const VectorType *T) { Visit(T->getElementType()); } VisitFunctionType(const FunctionType * T)376 void VisitFunctionType(const FunctionType *T) { Visit(T->getReturnType()); } VisitFunctionProtoType(const FunctionProtoType * T)377 void VisitFunctionProtoType(const FunctionProtoType *T) { 378 VisitFunctionType(T); 379 for (const QualType &PT : T->getParamTypes()) 380 Visit(PT); 381 } VisitTypeOfExprType(const TypeOfExprType * T)382 void VisitTypeOfExprType(const TypeOfExprType *T) { 383 Visit(T->getUnderlyingExpr()); 384 } VisitDecltypeType(const DecltypeType * T)385 void VisitDecltypeType(const DecltypeType *T) { 386 Visit(T->getUnderlyingExpr()); 387 } VisitUnaryTransformType(const UnaryTransformType * T)388 void VisitUnaryTransformType(const UnaryTransformType *T) { 389 Visit(T->getBaseType()); 390 } VisitAttributedType(const AttributedType * T)391 void VisitAttributedType(const AttributedType *T) { 392 // FIXME: AttrKind 393 if (T->getModifiedType() != T->getEquivalentType()) 394 Visit(T->getModifiedType()); 395 } VisitBTFTagAttributedType(const BTFTagAttributedType * T)396 void VisitBTFTagAttributedType(const BTFTagAttributedType *T) { 397 Visit(T->getWrappedType()); 398 } VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *)399 void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *) {} 400 void VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType * T)401 VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T) { 402 Visit(T->getArgumentPack()); 403 } VisitTemplateSpecializationType(const TemplateSpecializationType * T)404 void VisitTemplateSpecializationType(const TemplateSpecializationType *T) { 405 for (const auto &Arg : T->template_arguments()) 406 Visit(Arg); 407 } VisitObjCObjectPointerType(const ObjCObjectPointerType * T)408 void VisitObjCObjectPointerType(const ObjCObjectPointerType *T) { 409 Visit(T->getPointeeType()); 410 } VisitAtomicType(const AtomicType * T)411 void VisitAtomicType(const AtomicType *T) { Visit(T->getValueType()); } VisitPipeType(const PipeType * T)412 void VisitPipeType(const PipeType *T) { Visit(T->getElementType()); } VisitAdjustedType(const AdjustedType * T)413 void VisitAdjustedType(const AdjustedType *T) { Visit(T->getOriginalType()); } VisitPackExpansionType(const PackExpansionType * T)414 void VisitPackExpansionType(const PackExpansionType *T) { 415 if (!T->isSugared()) 416 Visit(T->getPattern()); 417 } 418 // FIXME: ElaboratedType, DependentNameType, 419 // DependentTemplateSpecializationType, ObjCObjectType 420 VisitTypedefDecl(const TypedefDecl * D)421 void VisitTypedefDecl(const TypedefDecl *D) { Visit(D->getUnderlyingType()); } 422 VisitEnumConstantDecl(const EnumConstantDecl * D)423 void VisitEnumConstantDecl(const EnumConstantDecl *D) { 424 if (const Expr *Init = D->getInitExpr()) 425 Visit(Init); 426 } 427 VisitFunctionDecl(const FunctionDecl * D)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 VisitFieldDecl(const FieldDecl * D)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 VisitVarDecl(const VarDecl * D)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 VisitDecompositionDecl(const DecompositionDecl * D)469 void VisitDecompositionDecl(const DecompositionDecl *D) { 470 VisitVarDecl(D); 471 for (const auto *B : D->bindings()) 472 Visit(B); 473 } 474 VisitBindingDecl(const BindingDecl * D)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 VisitFileScopeAsmDecl(const FileScopeAsmDecl * D)486 void VisitFileScopeAsmDecl(const FileScopeAsmDecl *D) { 487 Visit(D->getAsmString()); 488 } 489 VisitTopLevelStmtDecl(const TopLevelStmtDecl * D)490 void VisitTopLevelStmtDecl(const TopLevelStmtDecl *D) { Visit(D->getStmt()); } 491 VisitCapturedDecl(const CapturedDecl * D)492 void VisitCapturedDecl(const CapturedDecl *D) { Visit(D->getBody()); } 493 VisitOMPThreadPrivateDecl(const OMPThreadPrivateDecl * D)494 void VisitOMPThreadPrivateDecl(const OMPThreadPrivateDecl *D) { 495 for (const auto *E : D->varlists()) 496 Visit(E); 497 } 498 VisitOMPDeclareReductionDecl(const OMPDeclareReductionDecl * D)499 void VisitOMPDeclareReductionDecl(const OMPDeclareReductionDecl *D) { 500 Visit(D->getCombiner()); 501 if (const auto *Initializer = D->getInitializer()) 502 Visit(Initializer); 503 } 504 VisitOMPDeclareMapperDecl(const OMPDeclareMapperDecl * D)505 void VisitOMPDeclareMapperDecl(const OMPDeclareMapperDecl *D) { 506 for (const auto *C : D->clauselists()) 507 Visit(C); 508 } 509 VisitOMPCapturedExprDecl(const OMPCapturedExprDecl * D)510 void VisitOMPCapturedExprDecl(const OMPCapturedExprDecl *D) { 511 Visit(D->getInit()); 512 } 513 VisitOMPAllocateDecl(const OMPAllocateDecl * D)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> dumpTemplateDeclSpecialization(const SpecializationDecl * D)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> dumpTemplateDecl(const TemplateDecl * D)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 VisitTypeAliasDecl(const TypeAliasDecl * D)552 void VisitTypeAliasDecl(const TypeAliasDecl *D) { 553 Visit(D->getUnderlyingType()); 554 } 555 VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl * D)556 void VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D) { 557 dumpTemplateParameters(D->getTemplateParameters()); 558 Visit(D->getTemplatedDecl()); 559 } 560 VisitStaticAssertDecl(const StaticAssertDecl * D)561 void VisitStaticAssertDecl(const StaticAssertDecl *D) { 562 Visit(D->getAssertExpr()); 563 Visit(D->getMessage()); 564 } 565 VisitFunctionTemplateDecl(const FunctionTemplateDecl * D)566 void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) { 567 dumpTemplateDecl(D); 568 } 569 VisitClassTemplateDecl(const ClassTemplateDecl * D)570 void VisitClassTemplateDecl(const ClassTemplateDecl *D) { 571 dumpTemplateDecl(D); 572 } 573 VisitClassTemplateSpecializationDecl(const ClassTemplateSpecializationDecl * D)574 void VisitClassTemplateSpecializationDecl( 575 const ClassTemplateSpecializationDecl *D) { 576 dumpTemplateArgumentList(D->getTemplateArgs()); 577 } 578 VisitClassTemplatePartialSpecializationDecl(const ClassTemplatePartialSpecializationDecl * D)579 void VisitClassTemplatePartialSpecializationDecl( 580 const ClassTemplatePartialSpecializationDecl *D) { 581 VisitClassTemplateSpecializationDecl(D); 582 dumpTemplateParameters(D->getTemplateParameters()); 583 } 584 VisitVarTemplateDecl(const VarTemplateDecl * D)585 void VisitVarTemplateDecl(const VarTemplateDecl *D) { dumpTemplateDecl(D); } 586 VisitBuiltinTemplateDecl(const BuiltinTemplateDecl * D)587 void VisitBuiltinTemplateDecl(const BuiltinTemplateDecl *D) { 588 dumpTemplateParameters(D->getTemplateParameters()); 589 } 590 591 void VisitVarTemplateSpecializationDecl(const VarTemplateSpecializationDecl * D)592 VisitVarTemplateSpecializationDecl(const VarTemplateSpecializationDecl *D) { 593 dumpTemplateArgumentList(D->getTemplateArgs()); 594 VisitVarDecl(D); 595 } 596 VisitVarTemplatePartialSpecializationDecl(const VarTemplatePartialSpecializationDecl * D)597 void VisitVarTemplatePartialSpecializationDecl( 598 const VarTemplatePartialSpecializationDecl *D) { 599 dumpTemplateParameters(D->getTemplateParameters()); 600 VisitVarTemplateSpecializationDecl(D); 601 } 602 VisitTemplateTypeParmDecl(const TemplateTypeParmDecl * D)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 VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl * D)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 VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl * D)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 VisitConceptDecl(const ConceptDecl * D)629 void VisitConceptDecl(const ConceptDecl *D) { 630 dumpTemplateParameters(D->getTemplateParameters()); 631 Visit(D->getConstraintExpr()); 632 } 633 VisitImplicitConceptSpecializationDecl(const ImplicitConceptSpecializationDecl * CSD)634 void VisitImplicitConceptSpecializationDecl( 635 const ImplicitConceptSpecializationDecl *CSD) { 636 for (const TemplateArgument &Arg : CSD->getTemplateArguments()) 637 Visit(Arg); 638 } 639 VisitConceptSpecializationExpr(const ConceptSpecializationExpr * CSE)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 VisitUsingShadowDecl(const UsingShadowDecl * D)647 void VisitUsingShadowDecl(const UsingShadowDecl *D) { 648 if (auto *TD = dyn_cast<TypeDecl>(D->getUnderlyingDecl())) 649 Visit(TD->getTypeForDecl()); 650 } 651 VisitFriendDecl(const FriendDecl * D)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 VisitObjCMethodDecl(const ObjCMethodDecl * D)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 VisitObjCCategoryDecl(const ObjCCategoryDecl * D)675 void VisitObjCCategoryDecl(const ObjCCategoryDecl *D) { 676 dumpObjCTypeParamList(D->getTypeParamList()); 677 } 678 VisitObjCInterfaceDecl(const ObjCInterfaceDecl * D)679 void VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) { 680 dumpObjCTypeParamList(D->getTypeParamListAsWritten()); 681 } 682 VisitObjCImplementationDecl(const ObjCImplementationDecl * D)683 void VisitObjCImplementationDecl(const ObjCImplementationDecl *D) { 684 for (const auto &I : D->inits()) 685 Visit(I); 686 } 687 VisitBlockDecl(const BlockDecl * D)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 VisitDeclStmt(const DeclStmt * Node)697 void VisitDeclStmt(const DeclStmt *Node) { 698 for (const auto &D : Node->decls()) 699 Visit(D); 700 } 701 VisitAttributedStmt(const AttributedStmt * Node)702 void VisitAttributedStmt(const AttributedStmt *Node) { 703 for (const auto *A : Node->getAttrs()) 704 Visit(A); 705 } 706 VisitCXXCatchStmt(const CXXCatchStmt * Node)707 void VisitCXXCatchStmt(const CXXCatchStmt *Node) { 708 Visit(Node->getExceptionDecl()); 709 } 710 VisitCapturedStmt(const CapturedStmt * Node)711 void VisitCapturedStmt(const CapturedStmt *Node) { 712 Visit(Node->getCapturedDecl()); 713 } 714 VisitOMPExecutableDirective(const OMPExecutableDirective * Node)715 void VisitOMPExecutableDirective(const OMPExecutableDirective *Node) { 716 for (const auto *C : Node->clauses()) 717 Visit(C); 718 } 719 VisitInitListExpr(const InitListExpr * ILE)720 void VisitInitListExpr(const InitListExpr *ILE) { 721 if (auto *Filler = ILE->getArrayFiller()) { 722 Visit(Filler, "array_filler"); 723 } 724 } 725 VisitCXXParenListInitExpr(const CXXParenListInitExpr * PLIE)726 void VisitCXXParenListInitExpr(const CXXParenListInitExpr *PLIE) { 727 if (auto *Filler = PLIE->getArrayFiller()) { 728 Visit(Filler, "array_filler"); 729 } 730 } 731 VisitBlockExpr(const BlockExpr * Node)732 void VisitBlockExpr(const BlockExpr *Node) { Visit(Node->getBlockDecl()); } 733 VisitOpaqueValueExpr(const OpaqueValueExpr * Node)734 void VisitOpaqueValueExpr(const OpaqueValueExpr *Node) { 735 if (Expr *Source = Node->getSourceExpr()) 736 Visit(Source); 737 } 738 VisitGenericSelectionExpr(const GenericSelectionExpr * E)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 VisitRequiresExpr(const RequiresExpr * E)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 VisitLambdaExpr(const LambdaExpr * Node)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 VisitSizeOfPackExpr(const SizeOfPackExpr * Node)778 void VisitSizeOfPackExpr(const SizeOfPackExpr *Node) { 779 if (Node->isPartiallySubstituted()) 780 for (const auto &A : Node->getPartialArguments()) 781 Visit(A); 782 } 783 VisitSubstNonTypeTemplateParmExpr(const SubstNonTypeTemplateParmExpr * E)784 void VisitSubstNonTypeTemplateParmExpr(const SubstNonTypeTemplateParmExpr *E) { 785 Visit(E->getParameter()); 786 } VisitSubstNonTypeTemplateParmPackExpr(const SubstNonTypeTemplateParmPackExpr * E)787 void VisitSubstNonTypeTemplateParmPackExpr( 788 const SubstNonTypeTemplateParmPackExpr *E) { 789 Visit(E->getParameterPack()); 790 Visit(E->getArgumentPack()); 791 } 792 VisitObjCAtCatchStmt(const ObjCAtCatchStmt * Node)793 void VisitObjCAtCatchStmt(const ObjCAtCatchStmt *Node) { 794 if (const VarDecl *CatchParam = Node->getCatchParamDecl()) 795 Visit(CatchParam); 796 } 797 VisitCXXForRangeStmt(const CXXForRangeStmt * Node)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 VisitCallExpr(const CallExpr * Node)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 VisitCXXRewrittenBinaryOperator(const CXXRewrittenBinaryOperator * Node)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 VisitExpressionTemplateArgument(const TemplateArgument & TA)827 void VisitExpressionTemplateArgument(const TemplateArgument &TA) { 828 Visit(TA.getAsExpr()); 829 } 830 VisitTypeTemplateArgument(const TemplateArgument & TA)831 void VisitTypeTemplateArgument(const TemplateArgument &TA) { 832 Visit(TA.getAsType()); 833 } 834 VisitPackTemplateArgument(const TemplateArgument & TA)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