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