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