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