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