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