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