]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/clang/include/clang/AST/ASTNodeTraverser.h
Move all sources from the llvm project into contrib/llvm-project.
[FreeBSD/FreeBSD.git] / contrib / llvm-project / clang / include / clang / AST / ASTNodeTraverser.h
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   NodeDelegateType &getNodeDelegate() {
69     return getDerived().doGetNodeDelegate();
70   }
71   Derived &getDerived() { return *static_cast<Derived *>(this); }
72
73 public:
74   void setDeserialize(bool D) { Deserialize = D; }
75   bool getDeserialize() const { return Deserialize; }
76
77   void Visit(const Decl *D) {
78     getNodeDelegate().AddChild([=] {
79       getNodeDelegate().Visit(D);
80       if (!D)
81         return;
82
83       ConstDeclVisitor<Derived>::Visit(D);
84
85       for (const auto &A : D->attrs())
86         Visit(A);
87
88       if (const comments::FullComment *Comment =
89               D->getASTContext().getLocalCommentForDeclUncached(D))
90         Visit(Comment, Comment);
91
92       // Decls within functions are visited by the body.
93       if (!isa<FunctionDecl>(*D) && !isa<ObjCMethodDecl>(*D)) {
94         if (const auto *DC = dyn_cast<DeclContext>(D))
95           dumpDeclContext(DC);
96       }
97     });
98   }
99
100   void Visit(const Stmt *S, StringRef Label = {}) {
101     getNodeDelegate().AddChild(Label, [=] {
102       getNodeDelegate().Visit(S);
103
104       if (!S) {
105         return;
106       }
107
108       ConstStmtVisitor<Derived>::Visit(S);
109
110       // Some statements have custom mechanisms for dumping their children.
111       if (isa<DeclStmt>(S) || isa<GenericSelectionExpr>(S)) {
112         return;
113       }
114
115       for (const Stmt *SubStmt : S->children())
116         Visit(SubStmt);
117     });
118   }
119
120   void Visit(QualType T) {
121     SplitQualType SQT = T.split();
122     if (!SQT.Quals.hasQualifiers())
123       return Visit(SQT.Ty);
124
125     getNodeDelegate().AddChild([=] {
126       getNodeDelegate().Visit(T);
127       Visit(T.split().Ty);
128     });
129   }
130
131   void Visit(const Type *T) {
132     getNodeDelegate().AddChild([=] {
133       getNodeDelegate().Visit(T);
134       if (!T)
135         return;
136       TypeVisitor<Derived>::Visit(T);
137
138       QualType SingleStepDesugar =
139           T->getLocallyUnqualifiedSingleStepDesugaredType();
140       if (SingleStepDesugar != QualType(T, 0))
141         Visit(SingleStepDesugar);
142     });
143   }
144
145   void Visit(const Attr *A) {
146     getNodeDelegate().AddChild([=] {
147       getNodeDelegate().Visit(A);
148       ConstAttrVisitor<Derived>::Visit(A);
149     });
150   }
151
152   void Visit(const CXXCtorInitializer *Init) {
153     getNodeDelegate().AddChild([=] {
154       getNodeDelegate().Visit(Init);
155       Visit(Init->getInit());
156     });
157   }
158
159   void Visit(const TemplateArgument &A, SourceRange R = {},
160              const Decl *From = nullptr, const char *Label = nullptr) {
161     getNodeDelegate().AddChild([=] {
162       getNodeDelegate().Visit(A, R, From, Label);
163       ConstTemplateArgumentVisitor<Derived>::Visit(A);
164     });
165   }
166
167   void Visit(const BlockDecl::Capture &C) {
168     getNodeDelegate().AddChild([=] {
169       getNodeDelegate().Visit(C);
170       if (C.hasCopyExpr())
171         Visit(C.getCopyExpr());
172     });
173   }
174
175   void Visit(const OMPClause *C) {
176     getNodeDelegate().AddChild([=] {
177       getNodeDelegate().Visit(C);
178       for (const auto *S : C->children())
179         Visit(S);
180     });
181   }
182
183   void Visit(const GenericSelectionExpr::ConstAssociation &A) {
184     getNodeDelegate().AddChild([=] {
185       getNodeDelegate().Visit(A);
186       if (const TypeSourceInfo *TSI = A.getTypeSourceInfo())
187         Visit(TSI->getType());
188       Visit(A.getAssociationExpr());
189     });
190   }
191
192   void Visit(const comments::Comment *C, const comments::FullComment *FC) {
193     getNodeDelegate().AddChild([=] {
194       getNodeDelegate().Visit(C, FC);
195       if (!C) {
196         return;
197       }
198       comments::ConstCommentVisitor<Derived, void,
199                                     const comments::FullComment *>::visit(C,
200                                                                           FC);
201       for (comments::Comment::child_iterator I = C->child_begin(),
202                                              E = C->child_end();
203            I != E; ++I)
204         Visit(*I, FC);
205     });
206   }
207
208   void Visit(const ast_type_traits::DynTypedNode &N) {
209     // FIXME: Improve this with a switch or a visitor pattern.
210     if (const auto *D = N.get<Decl>())
211       Visit(D);
212     else if (const auto *S = N.get<Stmt>())
213       Visit(S);
214     else if (const auto *QT = N.get<QualType>())
215       Visit(*QT);
216     else if (const auto *T = N.get<Type>())
217       Visit(T);
218     else if (const auto *C = N.get<CXXCtorInitializer>())
219       Visit(C);
220     else if (const auto *C = N.get<OMPClause>())
221       Visit(C);
222     else if (const auto *T = N.get<TemplateArgument>())
223       Visit(*T);
224   }
225
226   void dumpDeclContext(const DeclContext *DC) {
227     if (!DC)
228       return;
229
230     for (const auto *D : (Deserialize ? DC->decls() : DC->noload_decls()))
231       Visit(D);
232   }
233
234   void dumpTemplateParameters(const TemplateParameterList *TPL) {
235     if (!TPL)
236       return;
237
238     for (const auto &TP : *TPL)
239       Visit(TP);
240   }
241
242   void
243   dumpASTTemplateArgumentListInfo(const ASTTemplateArgumentListInfo *TALI) {
244     if (!TALI)
245       return;
246
247     for (const auto &TA : TALI->arguments())
248       dumpTemplateArgumentLoc(TA);
249   }
250
251   void dumpTemplateArgumentLoc(const TemplateArgumentLoc &A,
252                                const Decl *From = nullptr,
253                                const char *Label = nullptr) {
254     Visit(A.getArgument(), A.getSourceRange(), From, Label);
255   }
256
257   void dumpTemplateArgumentList(const TemplateArgumentList &TAL) {
258     for (unsigned i = 0, e = TAL.size(); i < e; ++i)
259       Visit(TAL[i]);
260   }
261
262   void dumpObjCTypeParamList(const ObjCTypeParamList *typeParams) {
263     if (!typeParams)
264       return;
265
266     for (const auto &typeParam : *typeParams) {
267       Visit(typeParam);
268     }
269   }
270
271   void VisitComplexType(const ComplexType *T) { Visit(T->getElementType()); }
272   void VisitLocInfoType(const LocInfoType *T) {
273     Visit(T->getTypeSourceInfo()->getType());
274   }
275   void VisitPointerType(const PointerType *T) { Visit(T->getPointeeType()); }
276   void VisitBlockPointerType(const BlockPointerType *T) {
277     Visit(T->getPointeeType());
278   }
279   void VisitReferenceType(const ReferenceType *T) {
280     Visit(T->getPointeeType());
281   }
282   void VisitMemberPointerType(const MemberPointerType *T) {
283     Visit(T->getClass());
284     Visit(T->getPointeeType());
285   }
286   void VisitArrayType(const ArrayType *T) { Visit(T->getElementType()); }
287   void VisitVariableArrayType(const VariableArrayType *T) {
288     VisitArrayType(T);
289     Visit(T->getSizeExpr());
290   }
291   void VisitDependentSizedArrayType(const DependentSizedArrayType *T) {
292     Visit(T->getElementType());
293     Visit(T->getSizeExpr());
294   }
295   void VisitDependentSizedExtVectorType(const DependentSizedExtVectorType *T) {
296     Visit(T->getElementType());
297     Visit(T->getSizeExpr());
298   }
299   void VisitVectorType(const VectorType *T) { Visit(T->getElementType()); }
300   void VisitFunctionType(const FunctionType *T) { Visit(T->getReturnType()); }
301   void VisitFunctionProtoType(const FunctionProtoType *T) {
302     VisitFunctionType(T);
303     for (const QualType &PT : T->getParamTypes())
304       Visit(PT);
305   }
306   void VisitTypeOfExprType(const TypeOfExprType *T) {
307     Visit(T->getUnderlyingExpr());
308   }
309   void VisitDecltypeType(const DecltypeType *T) {
310     Visit(T->getUnderlyingExpr());
311   }
312   void VisitUnaryTransformType(const UnaryTransformType *T) {
313     Visit(T->getBaseType());
314   }
315   void VisitAttributedType(const AttributedType *T) {
316     // FIXME: AttrKind
317     Visit(T->getModifiedType());
318   }
319   void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) {
320     Visit(T->getReplacedParameter());
321   }
322   void
323   VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T) {
324     Visit(T->getReplacedParameter());
325     Visit(T->getArgumentPack());
326   }
327   void VisitTemplateSpecializationType(const TemplateSpecializationType *T) {
328     for (const auto &Arg : *T)
329       Visit(Arg);
330     if (T->isTypeAlias())
331       Visit(T->getAliasedType());
332   }
333   void VisitObjCObjectPointerType(const ObjCObjectPointerType *T) {
334     Visit(T->getPointeeType());
335   }
336   void VisitAtomicType(const AtomicType *T) { Visit(T->getValueType()); }
337   void VisitPipeType(const PipeType *T) { Visit(T->getElementType()); }
338   void VisitAdjustedType(const AdjustedType *T) { Visit(T->getOriginalType()); }
339   void VisitPackExpansionType(const PackExpansionType *T) {
340     if (!T->isSugared())
341       Visit(T->getPattern());
342   }
343   // FIXME: ElaboratedType, DependentNameType,
344   // DependentTemplateSpecializationType, ObjCObjectType
345
346   void VisitTypedefDecl(const TypedefDecl *D) { Visit(D->getUnderlyingType()); }
347
348   void VisitEnumConstantDecl(const EnumConstantDecl *D) {
349     if (const Expr *Init = D->getInitExpr())
350       Visit(Init);
351   }
352
353   void VisitFunctionDecl(const FunctionDecl *D) {
354     if (const auto *FTSI = D->getTemplateSpecializationInfo())
355       dumpTemplateArgumentList(*FTSI->TemplateArguments);
356
357     if (D->param_begin())
358       for (const auto *Parameter : D->parameters())
359         Visit(Parameter);
360
361     if (const auto *C = dyn_cast<CXXConstructorDecl>(D))
362       for (const auto *I : C->inits())
363         Visit(I);
364
365     if (D->doesThisDeclarationHaveABody())
366       Visit(D->getBody());
367   }
368
369   void VisitFieldDecl(const FieldDecl *D) {
370     if (D->isBitField())
371       Visit(D->getBitWidth());
372     if (Expr *Init = D->getInClassInitializer())
373       Visit(Init);
374   }
375
376   void VisitVarDecl(const VarDecl *D) {
377     if (D->hasInit())
378       Visit(D->getInit());
379   }
380
381   void VisitDecompositionDecl(const DecompositionDecl *D) {
382     VisitVarDecl(D);
383     for (const auto *B : D->bindings())
384       Visit(B);
385   }
386
387   void VisitBindingDecl(const BindingDecl *D) {
388     if (const auto *E = D->getBinding())
389       Visit(E);
390   }
391
392   void VisitFileScopeAsmDecl(const FileScopeAsmDecl *D) {
393     Visit(D->getAsmString());
394   }
395
396   void VisitCapturedDecl(const CapturedDecl *D) { Visit(D->getBody()); }
397
398   void VisitOMPThreadPrivateDecl(const OMPThreadPrivateDecl *D) {
399     for (const auto *E : D->varlists())
400       Visit(E);
401   }
402
403   void VisitOMPDeclareReductionDecl(const OMPDeclareReductionDecl *D) {
404     Visit(D->getCombiner());
405     if (const auto *Initializer = D->getInitializer())
406       Visit(Initializer);
407   }
408
409   void VisitOMPDeclareMapperDecl(const OMPDeclareMapperDecl *D) {
410     for (const auto *C : D->clauselists())
411       Visit(C);
412   }
413
414   void VisitOMPCapturedExprDecl(const OMPCapturedExprDecl *D) {
415     Visit(D->getInit());
416   }
417
418   void VisitOMPAllocateDecl(const OMPAllocateDecl *D) {
419     for (const auto *E : D->varlists())
420       Visit(E);
421     for (const auto *C : D->clauselists())
422       Visit(C);
423   }
424
425   template <typename SpecializationDecl>
426   void dumpTemplateDeclSpecialization(const SpecializationDecl *D) {
427     for (const auto *RedeclWithBadType : D->redecls()) {
428       // FIXME: The redecls() range sometimes has elements of a less-specific
429       // type. (In particular, ClassTemplateSpecializationDecl::redecls() gives
430       // us TagDecls, and should give CXXRecordDecls).
431       auto *Redecl = dyn_cast<SpecializationDecl>(RedeclWithBadType);
432       if (!Redecl) {
433         // Found the injected-class-name for a class template. This will be
434         // dumped as part of its surrounding class so we don't need to dump it
435         // here.
436         assert(isa<CXXRecordDecl>(RedeclWithBadType) &&
437                "expected an injected-class-name");
438         continue;
439       }
440       Visit(Redecl);
441     }
442   }
443
444   template <typename TemplateDecl>
445   void dumpTemplateDecl(const TemplateDecl *D) {
446     dumpTemplateParameters(D->getTemplateParameters());
447
448     Visit(D->getTemplatedDecl());
449
450     for (const auto *Child : D->specializations())
451       dumpTemplateDeclSpecialization(Child);
452   }
453
454   void VisitTypeAliasDecl(const TypeAliasDecl *D) {
455     Visit(D->getUnderlyingType());
456   }
457
458   void VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D) {
459     dumpTemplateParameters(D->getTemplateParameters());
460     Visit(D->getTemplatedDecl());
461   }
462
463   void VisitStaticAssertDecl(const StaticAssertDecl *D) {
464     Visit(D->getAssertExpr());
465     Visit(D->getMessage());
466   }
467
468   void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
469     dumpTemplateDecl(D);
470   }
471
472   void VisitClassTemplateDecl(const ClassTemplateDecl *D) {
473     dumpTemplateDecl(D);
474   }
475
476   void VisitClassTemplateSpecializationDecl(
477       const ClassTemplateSpecializationDecl *D) {
478     dumpTemplateArgumentList(D->getTemplateArgs());
479   }
480
481   void VisitClassTemplatePartialSpecializationDecl(
482       const ClassTemplatePartialSpecializationDecl *D) {
483     VisitClassTemplateSpecializationDecl(D);
484     dumpTemplateParameters(D->getTemplateParameters());
485   }
486
487   void VisitClassScopeFunctionSpecializationDecl(
488       const ClassScopeFunctionSpecializationDecl *D) {
489     Visit(D->getSpecialization());
490     dumpASTTemplateArgumentListInfo(D->getTemplateArgsAsWritten());
491   }
492   void VisitVarTemplateDecl(const VarTemplateDecl *D) { dumpTemplateDecl(D); }
493
494   void VisitBuiltinTemplateDecl(const BuiltinTemplateDecl *D) {
495     dumpTemplateParameters(D->getTemplateParameters());
496   }
497
498   void
499   VisitVarTemplateSpecializationDecl(const VarTemplateSpecializationDecl *D) {
500     dumpTemplateArgumentList(D->getTemplateArgs());
501     VisitVarDecl(D);
502   }
503
504   void VisitVarTemplatePartialSpecializationDecl(
505       const VarTemplatePartialSpecializationDecl *D) {
506     dumpTemplateParameters(D->getTemplateParameters());
507     VisitVarTemplateSpecializationDecl(D);
508   }
509
510   void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) {
511     if (D->hasDefaultArgument())
512       Visit(D->getDefaultArgument(), SourceRange(),
513             D->getDefaultArgStorage().getInheritedFrom(),
514             D->defaultArgumentWasInherited() ? "inherited from" : "previous");
515   }
516
517   void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D) {
518     if (D->hasDefaultArgument())
519       Visit(D->getDefaultArgument(), SourceRange(),
520             D->getDefaultArgStorage().getInheritedFrom(),
521             D->defaultArgumentWasInherited() ? "inherited from" : "previous");
522   }
523
524   void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D) {
525     dumpTemplateParameters(D->getTemplateParameters());
526     if (D->hasDefaultArgument())
527       dumpTemplateArgumentLoc(
528           D->getDefaultArgument(), D->getDefaultArgStorage().getInheritedFrom(),
529           D->defaultArgumentWasInherited() ? "inherited from" : "previous");
530   }
531
532   void VisitConceptDecl(const ConceptDecl *D) {
533     dumpTemplateParameters(D->getTemplateParameters());
534     Visit(D->getConstraintExpr());
535   }
536
537   void VisitUsingShadowDecl(const UsingShadowDecl *D) {
538     if (auto *TD = dyn_cast<TypeDecl>(D->getUnderlyingDecl()))
539       Visit(TD->getTypeForDecl());
540   }
541
542   void VisitFriendDecl(const FriendDecl *D) {
543     if (!D->getFriendType())
544       Visit(D->getFriendDecl());
545   }
546
547   void VisitObjCMethodDecl(const ObjCMethodDecl *D) {
548     if (D->isThisDeclarationADefinition())
549       dumpDeclContext(D);
550     else
551       for (const ParmVarDecl *Parameter : D->parameters())
552         Visit(Parameter);
553
554     if (D->hasBody())
555       Visit(D->getBody());
556   }
557
558   void VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
559     dumpObjCTypeParamList(D->getTypeParamList());
560   }
561
562   void VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
563     dumpObjCTypeParamList(D->getTypeParamListAsWritten());
564   }
565
566   void VisitObjCImplementationDecl(const ObjCImplementationDecl *D) {
567     for (const auto &I : D->inits())
568       Visit(I);
569   }
570
571   void VisitBlockDecl(const BlockDecl *D) {
572     for (const auto &I : D->parameters())
573       Visit(I);
574
575     for (const auto &I : D->captures())
576       Visit(I);
577     Visit(D->getBody());
578   }
579
580   void VisitDeclStmt(const DeclStmt *Node) {
581     for (const auto &D : Node->decls())
582       Visit(D);
583   }
584
585   void VisitAttributedStmt(const AttributedStmt *Node) {
586     for (const auto *A : Node->getAttrs())
587       Visit(A);
588   }
589
590   void VisitCXXCatchStmt(const CXXCatchStmt *Node) {
591     Visit(Node->getExceptionDecl());
592   }
593
594   void VisitCapturedStmt(const CapturedStmt *Node) {
595     Visit(Node->getCapturedDecl());
596   }
597
598   void VisitOMPExecutableDirective(const OMPExecutableDirective *Node) {
599     for (const auto *C : Node->clauses())
600       Visit(C);
601   }
602
603   void VisitInitListExpr(const InitListExpr *ILE) {
604     if (auto *Filler = ILE->getArrayFiller()) {
605       Visit(Filler, "array_filler");
606     }
607   }
608
609   void VisitBlockExpr(const BlockExpr *Node) { Visit(Node->getBlockDecl()); }
610
611   void VisitOpaqueValueExpr(const OpaqueValueExpr *Node) {
612     if (Expr *Source = Node->getSourceExpr())
613       Visit(Source);
614   }
615
616   void VisitGenericSelectionExpr(const GenericSelectionExpr *E) {
617     Visit(E->getControllingExpr());
618     Visit(E->getControllingExpr()->getType()); // FIXME: remove
619
620     for (const auto &Assoc : E->associations()) {
621       Visit(Assoc);
622     }
623   }
624
625   void VisitLambdaExpr(const LambdaExpr *Node) {
626     Visit(Node->getLambdaClass());
627   }
628
629   void VisitSizeOfPackExpr(const SizeOfPackExpr *Node) {
630     if (Node->isPartiallySubstituted())
631       for (const auto &A : Node->getPartialArguments())
632         Visit(A);
633   }
634
635   void VisitObjCAtCatchStmt(const ObjCAtCatchStmt *Node) {
636     if (const VarDecl *CatchParam = Node->getCatchParamDecl())
637       Visit(CatchParam);
638   }
639
640   void VisitExpressionTemplateArgument(const TemplateArgument &TA) {
641     Visit(TA.getAsExpr());
642   }
643   void VisitPackTemplateArgument(const TemplateArgument &TA) {
644     for (const auto &TArg : TA.pack_elements())
645       Visit(TArg);
646   }
647
648   // Implements Visit methods for Attrs.
649 #include "clang/AST/AttrNodeTraverse.inc"
650 };
651
652 } // namespace clang
653
654 #endif // LLVM_CLANG_AST_ASTNODETRAVERSER_H