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

source code of clang/include/clang/AST/ASTNodeTraverser.h