xref: /openbsd-src/gnu/llvm/clang/tools/libclang/CursorVisitor.h (revision 1a8dbaac879b9f3335ad7fb25429ce63ac1d6bac)
1 //===- CursorVisitor.h - CursorVisitor interface ----------------*- C++ -*-===//
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 #ifndef LLVM_CLANG_TOOLS_LIBCLANG_CURSORVISITOR_H
10 #define LLVM_CLANG_TOOLS_LIBCLANG_CURSORVISITOR_H
11 
12 #include "CXCursor.h"
13 #include "CXTranslationUnit.h"
14 #include "Index_Internal.h"
15 #include "clang/AST/DeclVisitor.h"
16 #include "clang/AST/TypeLocVisitor.h"
17 
18 namespace clang {
19   class PreprocessingRecord;
20   class ASTUnit;
21 
22 namespace cxcursor {
23 
24 class VisitorJob {
25 public:
26   enum Kind { DeclVisitKind, StmtVisitKind, MemberExprPartsKind,
27               TypeLocVisitKind, OverloadExprPartsKind,
28               DeclRefExprPartsKind, LabelRefVisitKind,
29               ExplicitTemplateArgsVisitKind,
30               NestedNameSpecifierLocVisitKind,
31               DeclarationNameInfoVisitKind,
32               MemberRefVisitKind, SizeOfPackExprPartsKind,
33               LambdaExprPartsKind, PostChildrenVisitKind };
34 protected:
35   const void *data[3];
36   CXCursor parent;
37   Kind K;
38   VisitorJob(CXCursor C, Kind k, const void *d1, const void *d2 = nullptr,
39              const void *d3 = nullptr)
40     : parent(C), K(k) {
41     data[0] = d1;
42     data[1] = d2;
43     data[2] = d3;
44   }
45 public:
46   Kind getKind() const { return K; }
47   const CXCursor &getParent() const { return parent; }
48 };
49 
50 typedef SmallVector<VisitorJob, 10> VisitorWorkList;
51 
52 // Cursor visitor.
53 class CursorVisitor : public DeclVisitor<CursorVisitor, bool>,
54                       public TypeLocVisitor<CursorVisitor, bool>
55 {
56 public:
57   /// Callback called after child nodes of a cursor have been visited.
58   /// Return true to break visitation or false to continue.
59   typedef bool (*PostChildrenVisitorTy)(CXCursor cursor,
60                                         CXClientData client_data);
61 
62 private:
63   /// The translation unit we are traversing.
64   CXTranslationUnit TU;
65   ASTUnit *AU;
66 
67   /// The parent cursor whose children we are traversing.
68   CXCursor Parent;
69 
70   /// The declaration that serves at the parent of any statement or
71   /// expression nodes.
72   const Decl *StmtParent;
73 
74   /// The visitor function.
75   CXCursorVisitor Visitor;
76 
77   PostChildrenVisitorTy PostChildrenVisitor;
78 
79   /// The opaque client data, to be passed along to the visitor.
80   CXClientData ClientData;
81 
82   /// Whether we should visit the preprocessing record entries last,
83   /// after visiting other declarations.
84   bool VisitPreprocessorLast;
85 
86   /// Whether we should visit declarations or preprocessing record
87   /// entries that are #included inside the \arg RegionOfInterest.
88   bool VisitIncludedEntities;
89 
90   /// When valid, a source range to which the cursor should restrict
91   /// its search.
92   SourceRange RegionOfInterest;
93 
94   /// Whether we should only visit declarations and not preprocessing
95   /// record entries.
96   bool VisitDeclsOnly;
97 
98   // FIXME: Eventually remove.  This part of a hack to support proper
99   // iteration over all Decls contained lexically within an ObjC container.
100   DeclContext::decl_iterator *DI_current;
101   DeclContext::decl_iterator DE_current;
102   SmallVectorImpl<Decl *>::iterator *FileDI_current;
103   SmallVectorImpl<Decl *>::iterator FileDE_current;
104 
105   // Cache of pre-allocated worklists for data-recursion walk of Stmts.
106   SmallVector<VisitorWorkList*, 5> WorkListFreeList;
107   SmallVector<VisitorWorkList*, 5> WorkListCache;
108 
109   using DeclVisitor<CursorVisitor, bool>::Visit;
110   using TypeLocVisitor<CursorVisitor, bool>::Visit;
111 
112   /// Determine whether this particular source range comes before, comes
113   /// after, or overlaps the region of interest.
114   ///
115   /// \param R a half-open source range retrieved from the abstract syntax tree.
116   RangeComparisonResult CompareRegionOfInterest(SourceRange R);
117 
118   bool visitDeclsFromFileRegion(FileID File, unsigned Offset, unsigned Length);
119 
120   class SetParentRAII {
121     CXCursor &Parent;
122     const Decl *&StmtParent;
123     CXCursor OldParent;
124 
125   public:
126     SetParentRAII(CXCursor &Parent, const Decl *&StmtParent,
127                   CXCursor NewParent)
128       : Parent(Parent), StmtParent(StmtParent), OldParent(Parent)
129     {
130       Parent = NewParent;
131       if (clang_isDeclaration(Parent.kind))
132         StmtParent = getCursorDecl(Parent);
133     }
134 
135     ~SetParentRAII() {
136       Parent = OldParent;
137       if (clang_isDeclaration(Parent.kind))
138         StmtParent = getCursorDecl(Parent);
139     }
140   };
141 
142 public:
143   CursorVisitor(CXTranslationUnit TU, CXCursorVisitor Visitor,
144                 CXClientData ClientData,
145                 bool VisitPreprocessorLast,
146                 bool VisitIncludedPreprocessingEntries = false,
147                 SourceRange RegionOfInterest = SourceRange(),
148                 bool VisitDeclsOnly = false,
149                 PostChildrenVisitorTy PostChildrenVisitor = nullptr)
150     : TU(TU), AU(cxtu::getASTUnit(TU)),
151       Visitor(Visitor), PostChildrenVisitor(PostChildrenVisitor),
152       ClientData(ClientData),
153       VisitPreprocessorLast(VisitPreprocessorLast),
154       VisitIncludedEntities(VisitIncludedPreprocessingEntries),
155       RegionOfInterest(RegionOfInterest),
156       VisitDeclsOnly(VisitDeclsOnly),
157       DI_current(nullptr), FileDI_current(nullptr)
158   {
159     Parent.kind = CXCursor_NoDeclFound;
160     Parent.data[0] = nullptr;
161     Parent.data[1] = nullptr;
162     Parent.data[2] = nullptr;
163     StmtParent = nullptr;
164   }
165 
166   ~CursorVisitor() {
167     // Free the pre-allocated worklists for data-recursion.
168     for (SmallVectorImpl<VisitorWorkList*>::iterator
169           I = WorkListCache.begin(), E = WorkListCache.end(); I != E; ++I) {
170       delete *I;
171     }
172   }
173 
174   ASTUnit *getASTUnit() const { return AU; }
175   CXTranslationUnit getTU() const { return TU; }
176 
177   bool Visit(CXCursor Cursor, bool CheckedRegionOfInterest = false);
178 
179   /// Visit declarations and preprocessed entities for the file region
180   /// designated by \see RegionOfInterest.
181   bool visitFileRegion();
182 
183   bool visitPreprocessedEntitiesInRegion();
184 
185   bool shouldVisitIncludedEntities() const {
186     return VisitIncludedEntities;
187   }
188 
189   template<typename InputIterator>
190   bool visitPreprocessedEntities(InputIterator First, InputIterator Last,
191                                  PreprocessingRecord &PPRec,
192                                  FileID FID = FileID());
193 
194   bool VisitChildren(CXCursor Parent);
195 
196   // Declaration visitors
197   bool VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D);
198   bool VisitTypeAliasDecl(TypeAliasDecl *D);
199   bool VisitAttributes(Decl *D);
200   bool VisitBlockDecl(BlockDecl *B);
201   bool VisitCXXRecordDecl(CXXRecordDecl *D);
202   Optional<bool> shouldVisitCursor(CXCursor C);
203   bool VisitDeclContext(DeclContext *DC);
204   bool VisitTranslationUnitDecl(TranslationUnitDecl *D);
205   bool VisitTypedefDecl(TypedefDecl *D);
206   bool VisitTagDecl(TagDecl *D);
207   bool VisitClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl *D);
208   bool VisitClassTemplatePartialSpecializationDecl(
209                                      ClassTemplatePartialSpecializationDecl *D);
210   bool VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
211   bool VisitEnumConstantDecl(EnumConstantDecl *D);
212   bool VisitDeclaratorDecl(DeclaratorDecl *DD);
213   bool VisitFunctionDecl(FunctionDecl *ND);
214   bool VisitFieldDecl(FieldDecl *D);
215   bool VisitVarDecl(VarDecl *);
216   bool VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
217   bool VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
218   bool VisitClassTemplateDecl(ClassTemplateDecl *D);
219   bool VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
220   bool VisitObjCTypeParamDecl(ObjCTypeParamDecl *D);
221   bool VisitObjCMethodDecl(ObjCMethodDecl *ND);
222   bool VisitObjCContainerDecl(ObjCContainerDecl *D);
223   bool VisitObjCCategoryDecl(ObjCCategoryDecl *ND);
224   bool VisitObjCProtocolDecl(ObjCProtocolDecl *PID);
225   bool VisitObjCPropertyDecl(ObjCPropertyDecl *PD);
226   bool VisitObjCTypeParamList(ObjCTypeParamList *typeParamList);
227   bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
228   bool VisitObjCImplDecl(ObjCImplDecl *D);
229   bool VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
230   bool VisitObjCImplementationDecl(ObjCImplementationDecl *D);
231   // FIXME: ObjCCompatibleAliasDecl requires aliased-class locations.
232   bool VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PD);
233   bool VisitLinkageSpecDecl(LinkageSpecDecl *D);
234   bool VisitNamespaceDecl(NamespaceDecl *D);
235   bool VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
236   bool VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
237   bool VisitUsingDecl(UsingDecl *D);
238   bool VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
239   bool VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
240   bool VisitStaticAssertDecl(StaticAssertDecl *D);
241   bool VisitFriendDecl(FriendDecl *D);
242 
243   // Name visitor
244   bool VisitDeclarationNameInfo(DeclarationNameInfo Name);
245   bool VisitNestedNameSpecifier(NestedNameSpecifier *NNS, SourceRange Range);
246   bool VisitNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS);
247 
248   // Template visitors
249   bool VisitTemplateParameters(const TemplateParameterList *Params);
250   bool VisitTemplateName(TemplateName Name, SourceLocation Loc);
251   bool VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL);
252 
253   // Type visitors
254 #define ABSTRACT_TYPELOC(CLASS, PARENT)
255 #define TYPELOC(CLASS, PARENT) \
256   bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc);
257 #include "clang/AST/TypeLocNodes.def"
258 
259   bool VisitTagTypeLoc(TagTypeLoc TL);
260   bool VisitArrayTypeLoc(ArrayTypeLoc TL);
261   bool VisitFunctionTypeLoc(FunctionTypeLoc TL, bool SkipResultType = false);
262 
263   // Data-recursive visitor functions.
264   bool IsInRegionOfInterest(CXCursor C);
265   bool RunVisitorWorkList(VisitorWorkList &WL);
266   void EnqueueWorkList(VisitorWorkList &WL, const Stmt *S);
267   LLVM_ATTRIBUTE_NOINLINE bool Visit(const Stmt *S);
268 
269 private:
270   Optional<bool> handleDeclForVisitation(const Decl *D);
271 };
272 
273 }
274 }
275 
276 #endif
277 
278