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->isSubstitutionFailure()) 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 } VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType * T)389 void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) { 390 Visit(T->getReplacedParameter()); 391 } 392 void VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType * T)393 VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T) { 394 Visit(T->getReplacedParameter()); 395 Visit(T->getArgumentPack()); 396 } VisitTemplateSpecializationType(const TemplateSpecializationType * T)397 void VisitTemplateSpecializationType(const TemplateSpecializationType *T) { 398 for (const auto &Arg : *T) 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 if (const auto *E = D->getBinding()) 468 Visit(E); 469 } 470 VisitFileScopeAsmDecl(const FileScopeAsmDecl * D)471 void VisitFileScopeAsmDecl(const FileScopeAsmDecl *D) { 472 Visit(D->getAsmString()); 473 } 474 VisitCapturedDecl(const CapturedDecl * D)475 void VisitCapturedDecl(const CapturedDecl *D) { Visit(D->getBody()); } 476 VisitOMPThreadPrivateDecl(const OMPThreadPrivateDecl * D)477 void VisitOMPThreadPrivateDecl(const OMPThreadPrivateDecl *D) { 478 for (const auto *E : D->varlists()) 479 Visit(E); 480 } 481 VisitOMPDeclareReductionDecl(const OMPDeclareReductionDecl * D)482 void VisitOMPDeclareReductionDecl(const OMPDeclareReductionDecl *D) { 483 Visit(D->getCombiner()); 484 if (const auto *Initializer = D->getInitializer()) 485 Visit(Initializer); 486 } 487 VisitOMPDeclareMapperDecl(const OMPDeclareMapperDecl * D)488 void VisitOMPDeclareMapperDecl(const OMPDeclareMapperDecl *D) { 489 for (const auto *C : D->clauselists()) 490 Visit(C); 491 } 492 VisitOMPCapturedExprDecl(const OMPCapturedExprDecl * D)493 void VisitOMPCapturedExprDecl(const OMPCapturedExprDecl *D) { 494 Visit(D->getInit()); 495 } 496 VisitOMPAllocateDecl(const OMPAllocateDecl * D)497 void VisitOMPAllocateDecl(const OMPAllocateDecl *D) { 498 for (const auto *E : D->varlists()) 499 Visit(E); 500 for (const auto *C : D->clauselists()) 501 Visit(C); 502 } 503 504 template <typename SpecializationDecl> dumpTemplateDeclSpecialization(const SpecializationDecl * D)505 void dumpTemplateDeclSpecialization(const SpecializationDecl *D) { 506 for (const auto *RedeclWithBadType : D->redecls()) { 507 // FIXME: The redecls() range sometimes has elements of a less-specific 508 // type. (In particular, ClassTemplateSpecializationDecl::redecls() gives 509 // us TagDecls, and should give CXXRecordDecls). 510 auto *Redecl = dyn_cast<SpecializationDecl>(RedeclWithBadType); 511 if (!Redecl) { 512 // Found the injected-class-name for a class template. This will be 513 // dumped as part of its surrounding class so we don't need to dump it 514 // here. 515 assert(isa<CXXRecordDecl>(RedeclWithBadType) && 516 "expected an injected-class-name"); 517 continue; 518 } 519 Visit(Redecl); 520 } 521 } 522 523 template <typename TemplateDecl> dumpTemplateDecl(const TemplateDecl * D)524 void dumpTemplateDecl(const TemplateDecl *D) { 525 dumpTemplateParameters(D->getTemplateParameters()); 526 527 Visit(D->getTemplatedDecl()); 528 529 if (Traversal == TK_AsIs) { 530 for (const auto *Child : D->specializations()) 531 dumpTemplateDeclSpecialization(Child); 532 } 533 } 534 VisitTypeAliasDecl(const TypeAliasDecl * D)535 void VisitTypeAliasDecl(const TypeAliasDecl *D) { 536 Visit(D->getUnderlyingType()); 537 } 538 VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl * D)539 void VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D) { 540 dumpTemplateParameters(D->getTemplateParameters()); 541 Visit(D->getTemplatedDecl()); 542 } 543 VisitStaticAssertDecl(const StaticAssertDecl * D)544 void VisitStaticAssertDecl(const StaticAssertDecl *D) { 545 Visit(D->getAssertExpr()); 546 Visit(D->getMessage()); 547 } 548 VisitFunctionTemplateDecl(const FunctionTemplateDecl * D)549 void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) { 550 dumpTemplateDecl(D); 551 } 552 VisitClassTemplateDecl(const ClassTemplateDecl * D)553 void VisitClassTemplateDecl(const ClassTemplateDecl *D) { 554 dumpTemplateDecl(D); 555 } 556 VisitClassTemplateSpecializationDecl(const ClassTemplateSpecializationDecl * D)557 void VisitClassTemplateSpecializationDecl( 558 const ClassTemplateSpecializationDecl *D) { 559 dumpTemplateArgumentList(D->getTemplateArgs()); 560 } 561 VisitClassTemplatePartialSpecializationDecl(const ClassTemplatePartialSpecializationDecl * D)562 void VisitClassTemplatePartialSpecializationDecl( 563 const ClassTemplatePartialSpecializationDecl *D) { 564 VisitClassTemplateSpecializationDecl(D); 565 dumpTemplateParameters(D->getTemplateParameters()); 566 } 567 VisitClassScopeFunctionSpecializationDecl(const ClassScopeFunctionSpecializationDecl * D)568 void VisitClassScopeFunctionSpecializationDecl( 569 const ClassScopeFunctionSpecializationDecl *D) { 570 Visit(D->getSpecialization()); 571 dumpASTTemplateArgumentListInfo(D->getTemplateArgsAsWritten()); 572 } VisitVarTemplateDecl(const VarTemplateDecl * D)573 void VisitVarTemplateDecl(const VarTemplateDecl *D) { dumpTemplateDecl(D); } 574 VisitBuiltinTemplateDecl(const BuiltinTemplateDecl * D)575 void VisitBuiltinTemplateDecl(const BuiltinTemplateDecl *D) { 576 dumpTemplateParameters(D->getTemplateParameters()); 577 } 578 579 void VisitVarTemplateSpecializationDecl(const VarTemplateSpecializationDecl * D)580 VisitVarTemplateSpecializationDecl(const VarTemplateSpecializationDecl *D) { 581 dumpTemplateArgumentList(D->getTemplateArgs()); 582 VisitVarDecl(D); 583 } 584 VisitVarTemplatePartialSpecializationDecl(const VarTemplatePartialSpecializationDecl * D)585 void VisitVarTemplatePartialSpecializationDecl( 586 const VarTemplatePartialSpecializationDecl *D) { 587 dumpTemplateParameters(D->getTemplateParameters()); 588 VisitVarTemplateSpecializationDecl(D); 589 } 590 VisitTemplateTypeParmDecl(const TemplateTypeParmDecl * D)591 void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) { 592 if (const auto *TC = D->getTypeConstraint()) 593 Visit(TC->getImmediatelyDeclaredConstraint()); 594 if (D->hasDefaultArgument()) 595 Visit(D->getDefaultArgument(), SourceRange(), 596 D->getDefaultArgStorage().getInheritedFrom(), 597 D->defaultArgumentWasInherited() ? "inherited from" : "previous"); 598 } 599 VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl * D)600 void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D) { 601 if (const auto *E = D->getPlaceholderTypeConstraint()) 602 Visit(E); 603 if (D->hasDefaultArgument()) 604 Visit(D->getDefaultArgument(), SourceRange(), 605 D->getDefaultArgStorage().getInheritedFrom(), 606 D->defaultArgumentWasInherited() ? "inherited from" : "previous"); 607 } 608 VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl * D)609 void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D) { 610 dumpTemplateParameters(D->getTemplateParameters()); 611 if (D->hasDefaultArgument()) 612 dumpTemplateArgumentLoc( 613 D->getDefaultArgument(), D->getDefaultArgStorage().getInheritedFrom(), 614 D->defaultArgumentWasInherited() ? "inherited from" : "previous"); 615 } 616 VisitConceptDecl(const ConceptDecl * D)617 void VisitConceptDecl(const ConceptDecl *D) { 618 dumpTemplateParameters(D->getTemplateParameters()); 619 Visit(D->getConstraintExpr()); 620 } 621 VisitConceptSpecializationExpr(const ConceptSpecializationExpr * CSE)622 void VisitConceptSpecializationExpr(const ConceptSpecializationExpr *CSE) { 623 if (CSE->hasExplicitTemplateArgs()) 624 for (const auto &ArgLoc : CSE->getTemplateArgsAsWritten()->arguments()) 625 dumpTemplateArgumentLoc(ArgLoc); 626 } 627 VisitUsingShadowDecl(const UsingShadowDecl * D)628 void VisitUsingShadowDecl(const UsingShadowDecl *D) { 629 if (auto *TD = dyn_cast<TypeDecl>(D->getUnderlyingDecl())) 630 Visit(TD->getTypeForDecl()); 631 } 632 VisitFriendDecl(const FriendDecl * D)633 void VisitFriendDecl(const FriendDecl *D) { 634 if (!D->getFriendType()) 635 Visit(D->getFriendDecl()); 636 } 637 VisitObjCMethodDecl(const ObjCMethodDecl * D)638 void VisitObjCMethodDecl(const ObjCMethodDecl *D) { 639 if (D->isThisDeclarationADefinition()) 640 dumpDeclContext(D); 641 else 642 for (const ParmVarDecl *Parameter : D->parameters()) 643 Visit(Parameter); 644 645 if (D->hasBody()) 646 Visit(D->getBody()); 647 } 648 VisitObjCCategoryDecl(const ObjCCategoryDecl * D)649 void VisitObjCCategoryDecl(const ObjCCategoryDecl *D) { 650 dumpObjCTypeParamList(D->getTypeParamList()); 651 } 652 VisitObjCInterfaceDecl(const ObjCInterfaceDecl * D)653 void VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) { 654 dumpObjCTypeParamList(D->getTypeParamListAsWritten()); 655 } 656 VisitObjCImplementationDecl(const ObjCImplementationDecl * D)657 void VisitObjCImplementationDecl(const ObjCImplementationDecl *D) { 658 for (const auto &I : D->inits()) 659 Visit(I); 660 } 661 VisitBlockDecl(const BlockDecl * D)662 void VisitBlockDecl(const BlockDecl *D) { 663 for (const auto &I : D->parameters()) 664 Visit(I); 665 666 for (const auto &I : D->captures()) 667 Visit(I); 668 Visit(D->getBody()); 669 } 670 VisitDeclStmt(const DeclStmt * Node)671 void VisitDeclStmt(const DeclStmt *Node) { 672 for (const auto &D : Node->decls()) 673 Visit(D); 674 } 675 VisitAttributedStmt(const AttributedStmt * Node)676 void VisitAttributedStmt(const AttributedStmt *Node) { 677 for (const auto *A : Node->getAttrs()) 678 Visit(A); 679 } 680 VisitCXXCatchStmt(const CXXCatchStmt * Node)681 void VisitCXXCatchStmt(const CXXCatchStmt *Node) { 682 Visit(Node->getExceptionDecl()); 683 } 684 VisitCapturedStmt(const CapturedStmt * Node)685 void VisitCapturedStmt(const CapturedStmt *Node) { 686 Visit(Node->getCapturedDecl()); 687 } 688 VisitOMPExecutableDirective(const OMPExecutableDirective * Node)689 void VisitOMPExecutableDirective(const OMPExecutableDirective *Node) { 690 for (const auto *C : Node->clauses()) 691 Visit(C); 692 } 693 VisitInitListExpr(const InitListExpr * ILE)694 void VisitInitListExpr(const InitListExpr *ILE) { 695 if (auto *Filler = ILE->getArrayFiller()) { 696 Visit(Filler, "array_filler"); 697 } 698 } 699 VisitBlockExpr(const BlockExpr * Node)700 void VisitBlockExpr(const BlockExpr *Node) { Visit(Node->getBlockDecl()); } 701 VisitOpaqueValueExpr(const OpaqueValueExpr * Node)702 void VisitOpaqueValueExpr(const OpaqueValueExpr *Node) { 703 if (Expr *Source = Node->getSourceExpr()) 704 Visit(Source); 705 } 706 VisitGenericSelectionExpr(const GenericSelectionExpr * E)707 void VisitGenericSelectionExpr(const GenericSelectionExpr *E) { 708 Visit(E->getControllingExpr()); 709 Visit(E->getControllingExpr()->getType()); // FIXME: remove 710 711 for (const auto Assoc : E->associations()) { 712 Visit(Assoc); 713 } 714 } 715 VisitRequiresExpr(const RequiresExpr * E)716 void VisitRequiresExpr(const RequiresExpr *E) { 717 for (auto *D : E->getLocalParameters()) 718 Visit(D); 719 for (auto *R : E->getRequirements()) 720 Visit(R); 721 } 722 VisitLambdaExpr(const LambdaExpr * Node)723 void VisitLambdaExpr(const LambdaExpr *Node) { 724 if (Traversal == TK_IgnoreUnlessSpelledInSource) { 725 for (unsigned I = 0, N = Node->capture_size(); I != N; ++I) { 726 const auto *C = Node->capture_begin() + I; 727 if (!C->isExplicit()) 728 continue; 729 if (Node->isInitCapture(C)) 730 Visit(C->getCapturedVar()); 731 else 732 Visit(Node->capture_init_begin()[I]); 733 } 734 dumpTemplateParameters(Node->getTemplateParameterList()); 735 for (const auto *P : Node->getCallOperator()->parameters()) 736 Visit(P); 737 Visit(Node->getBody()); 738 } else { 739 return Visit(Node->getLambdaClass()); 740 } 741 } 742 VisitSizeOfPackExpr(const SizeOfPackExpr * Node)743 void VisitSizeOfPackExpr(const SizeOfPackExpr *Node) { 744 if (Node->isPartiallySubstituted()) 745 for (const auto &A : Node->getPartialArguments()) 746 Visit(A); 747 } 748 VisitSubstNonTypeTemplateParmExpr(const SubstNonTypeTemplateParmExpr * E)749 void VisitSubstNonTypeTemplateParmExpr(const SubstNonTypeTemplateParmExpr *E) { 750 Visit(E->getParameter()); 751 } VisitSubstNonTypeTemplateParmPackExpr(const SubstNonTypeTemplateParmPackExpr * E)752 void VisitSubstNonTypeTemplateParmPackExpr( 753 const SubstNonTypeTemplateParmPackExpr *E) { 754 Visit(E->getParameterPack()); 755 Visit(E->getArgumentPack()); 756 } 757 VisitObjCAtCatchStmt(const ObjCAtCatchStmt * Node)758 void VisitObjCAtCatchStmt(const ObjCAtCatchStmt *Node) { 759 if (const VarDecl *CatchParam = Node->getCatchParamDecl()) 760 Visit(CatchParam); 761 } 762 VisitCXXForRangeStmt(const CXXForRangeStmt * Node)763 void VisitCXXForRangeStmt(const CXXForRangeStmt *Node) { 764 if (Traversal == TK_IgnoreUnlessSpelledInSource) { 765 Visit(Node->getInit()); 766 Visit(Node->getLoopVariable()); 767 Visit(Node->getRangeInit()); 768 Visit(Node->getBody()); 769 } 770 } 771 VisitCallExpr(const CallExpr * Node)772 void VisitCallExpr(const CallExpr *Node) { 773 for (const auto *Child : 774 make_filter_range(Node->children(), [this](const Stmt *Child) { 775 if (Traversal != TK_IgnoreUnlessSpelledInSource) 776 return false; 777 return !isa<CXXDefaultArgExpr>(Child); 778 })) { 779 Visit(Child); 780 } 781 } 782 VisitCXXRewrittenBinaryOperator(const CXXRewrittenBinaryOperator * Node)783 void VisitCXXRewrittenBinaryOperator(const CXXRewrittenBinaryOperator *Node) { 784 if (Traversal == TK_IgnoreUnlessSpelledInSource) { 785 Visit(Node->getLHS()); 786 Visit(Node->getRHS()); 787 } else { 788 ConstStmtVisitor<Derived>::VisitCXXRewrittenBinaryOperator(Node); 789 } 790 } 791 VisitExpressionTemplateArgument(const TemplateArgument & TA)792 void VisitExpressionTemplateArgument(const TemplateArgument &TA) { 793 Visit(TA.getAsExpr()); 794 } 795 VisitTypeTemplateArgument(const TemplateArgument & TA)796 void VisitTypeTemplateArgument(const TemplateArgument &TA) { 797 Visit(TA.getAsType()); 798 } 799 VisitPackTemplateArgument(const TemplateArgument & TA)800 void VisitPackTemplateArgument(const TemplateArgument &TA) { 801 for (const auto &TArg : TA.pack_elements()) 802 Visit(TArg); 803 } 804 805 // Implements Visit methods for Attrs. 806 #include "clang/AST/AttrNodeTraverse.inc" 807 }; 808 809 } // namespace clang 810 811 #endif // LLVM_CLANG_AST_ASTNODETRAVERSER_H 812