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