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