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