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