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