1 //===- CursorVisitor.h - CursorVisitor interface ----------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_CLANG_TOOLS_LIBCLANG_CURSORVISITOR_H
10 #define LLVM_CLANG_TOOLS_LIBCLANG_CURSORVISITOR_H
13 #include "CXTranslationUnit.h"
14 #include "Index_Internal.h"
15 #include "clang/AST/DeclVisitor.h"
16 #include "clang/AST/TypeLocVisitor.h"
20 class PreprocessingRecord
;
36 OverloadExprPartsKind
,
39 ExplicitTemplateArgsVisitKind
,
40 NestedNameSpecifierLocVisitKind
,
41 DeclarationNameInfoVisitKind
,
43 SizeOfPackExprPartsKind
,
45 ConceptSpecializationExprVisitKind
,
46 RequiresExprVisitKind
,
54 VisitorJob(CXCursor C
, Kind k
, const void *d1
, const void *d2
= nullptr,
55 const void *d3
= nullptr)
63 Kind
getKind() const { return K
; }
64 const CXCursor
&getParent() const { return parent
; }
67 typedef SmallVector
<VisitorJob
, 10> VisitorWorkList
;
70 class CursorVisitor
: public DeclVisitor
<CursorVisitor
, bool>,
71 public TypeLocVisitor
<CursorVisitor
, bool> {
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
);
79 /// The translation unit we are traversing.
83 /// The parent cursor whose children we are traversing.
86 /// The declaration that serves at the parent of any statement or
88 const Decl
*StmtParent
;
90 /// The visitor function.
91 CXCursorVisitor Visitor
;
93 PostChildrenVisitorTy PostChildrenVisitor
;
95 /// The opaque client data, to be passed along to the visitor.
96 CXClientData ClientData
;
98 /// Whether we should visit the preprocessing record entries last,
99 /// after visiting other declarations.
100 bool VisitPreprocessorLast
;
102 /// Whether we should visit declarations or preprocessing record
103 /// entries that are #included inside the \arg RegionOfInterest.
104 bool VisitIncludedEntities
;
106 /// When valid, a source range to which the cursor should restrict
108 SourceRange RegionOfInterest
;
110 /// Whether we should only visit declarations and not preprocessing
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
;
121 // Cache of pre-allocated worklists for data-recursion walk of Stmts.
122 SmallVector
<VisitorWorkList
*, 5> WorkListFreeList
;
123 SmallVector
<VisitorWorkList
*, 5> WorkListCache
;
125 using DeclVisitor
<CursorVisitor
, bool>::Visit
;
126 using TypeLocVisitor
<CursorVisitor
, bool>::Visit
;
128 /// Determine whether this particular source range comes before, comes
129 /// after, or overlaps the region of interest.
131 /// \param R a half-open source range retrieved from the abstract syntax tree.
132 RangeComparisonResult
CompareRegionOfInterest(SourceRange R
);
134 bool visitDeclsFromFileRegion(FileID File
, unsigned Offset
, unsigned Length
);
136 class SetParentRAII
{
138 const Decl
*&StmtParent
;
142 SetParentRAII(CXCursor
&Parent
, const Decl
*&StmtParent
, CXCursor NewParent
)
143 : Parent(Parent
), StmtParent(StmtParent
), OldParent(Parent
) {
145 if (clang_isDeclaration(Parent
.kind
))
146 StmtParent
= getCursorDecl(Parent
);
151 if (clang_isDeclaration(Parent
.kind
))
152 StmtParent
= getCursorDecl(Parent
);
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;
177 // Free the pre-allocated worklists for data-recursion.
178 for (SmallVectorImpl
<VisitorWorkList
*>::iterator I
= WorkListCache
.begin(),
179 E
= WorkListCache
.end();
185 ASTUnit
*getASTUnit() const { return AU
; }
186 CXTranslationUnit
getTU() const { return TU
; }
188 bool Visit(CXCursor Cursor
, bool CheckedRegionOfInterest
= false);
190 /// Visit declarations and preprocessed entities for the file region
191 /// designated by \see RegionOfInterest.
192 bool visitFileRegion();
194 bool visitPreprocessedEntitiesInRegion();
196 bool shouldVisitIncludedEntities() const { return VisitIncludedEntities
; }
198 template <typename InputIterator
>
199 bool visitPreprocessedEntities(InputIterator First
, InputIterator Last
,
200 PreprocessingRecord
&PPRec
,
201 FileID FID
= FileID());
203 bool VisitChildren(CXCursor Parent
);
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
);
257 bool VisitDeclarationNameInfo(DeclarationNameInfo Name
);
258 bool VisitNestedNameSpecifier(NestedNameSpecifier
*NNS
, SourceRange Range
);
259 bool VisitNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS
);
262 bool VisitTemplateParameters(const TemplateParameterList
*Params
);
263 bool VisitTemplateName(TemplateName Name
, SourceLocation Loc
);
264 bool VisitTemplateArgumentLoc(const TemplateArgumentLoc
&TAL
);
267 #define ABSTRACT_TYPELOC(CLASS, PARENT)
268 #define TYPELOC(CLASS, PARENT) bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc);
269 #include "clang/AST/TypeLocNodes.def"
271 bool VisitTagTypeLoc(TagTypeLoc TL
);
272 bool VisitArrayTypeLoc(ArrayTypeLoc TL
);
273 bool VisitFunctionTypeLoc(FunctionTypeLoc TL
, bool SkipResultType
= false);
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
);
284 std::optional
<bool> handleDeclForVisitation(const Decl
*D
);
287 } // namespace cxcursor