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