blob: b0afa5a0b591adf8aa6bd34112abbfc8094880f5 [file] [log] [blame]
Nick Lewyckyacce2f82012-10-29 06:03:58 +00001//===- CursorVisitor.h - CursorVisitor interface ----------------*- C++ -*-===//
Argyrios Kyrtzidis52d87a62011-11-03 19:02:34 +00002//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Argyrios Kyrtzidis52d87a62011-11-03 19:02:34 +00006//
7//===----------------------------------------------------------------------===//
8
Benjamin Kramer2f5db8b2014-08-13 16:25:19 +00009#ifndef LLVM_CLANG_TOOLS_LIBCLANG_CURSORVISITOR_H
10#define LLVM_CLANG_TOOLS_LIBCLANG_CURSORVISITOR_H
Argyrios Kyrtzidis52d87a62011-11-03 19:02:34 +000011
Argyrios Kyrtzidis52d87a62011-11-03 19:02:34 +000012#include "CXCursor.h"
13#include "CXTranslationUnit.h"
Chandler Carruthcc0694c2012-12-04 09:25:21 +000014#include "Index_Internal.h"
Argyrios Kyrtzidis52d87a62011-11-03 19:02:34 +000015#include "clang/AST/DeclVisitor.h"
16#include "clang/AST/TypeLocVisitor.h"
17
18namespace clang {
19 class PreprocessingRecord;
20 class ASTUnit;
21
22namespace cxcursor {
23
24class VisitorJob {
25public:
26 enum Kind { DeclVisitKind, StmtVisitKind, MemberExprPartsKind,
27 TypeLocVisitKind, OverloadExprPartsKind,
28 DeclRefExprPartsKind, LabelRefVisitKind,
29 ExplicitTemplateArgsVisitKind,
30 NestedNameSpecifierLocVisitKind,
31 DeclarationNameInfoVisitKind,
Douglas Gregor30093832012-02-15 00:54:55 +000032 MemberRefVisitKind, SizeOfPackExprPartsKind,
Argyrios Kyrtzidisda188de2012-09-01 18:27:30 +000033 LambdaExprPartsKind, PostChildrenVisitKind };
Argyrios Kyrtzidis52d87a62011-11-03 19:02:34 +000034protected:
Dmitri Gribenkoe8354062013-01-26 15:29:08 +000035 const void *data[3];
Argyrios Kyrtzidis52d87a62011-11-03 19:02:34 +000036 CXCursor parent;
37 Kind K;
Craig Topper69186e72014-06-08 08:38:04 +000038 VisitorJob(CXCursor C, Kind k, const void *d1, const void *d2 = nullptr,
39 const void *d3 = nullptr)
Argyrios Kyrtzidis52d87a62011-11-03 19:02:34 +000040 : parent(C), K(k) {
41 data[0] = d1;
42 data[1] = d2;
43 data[2] = d3;
44 }
45public:
46 Kind getKind() const { return K; }
47 const CXCursor &getParent() const { return parent; }
Argyrios Kyrtzidis52d87a62011-11-03 19:02:34 +000048};
49
50typedef SmallVector<VisitorJob, 10> VisitorWorkList;
51
52// Cursor visitor.
53class CursorVisitor : public DeclVisitor<CursorVisitor, bool>,
54 public TypeLocVisitor<CursorVisitor, bool>
55{
Argyrios Kyrtzidisda188de2012-09-01 18:27:30 +000056public:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000057 /// Callback called after child nodes of a cursor have been visited.
Argyrios Kyrtzidisda188de2012-09-01 18:27:30 +000058 /// Return true to break visitation or false to continue.
59 typedef bool (*PostChildrenVisitorTy)(CXCursor cursor,
60 CXClientData client_data);
61
62private:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000063 /// The translation unit we are traversing.
Argyrios Kyrtzidis52d87a62011-11-03 19:02:34 +000064 CXTranslationUnit TU;
65 ASTUnit *AU;
66
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000067 /// The parent cursor whose children we are traversing.
Argyrios Kyrtzidis52d87a62011-11-03 19:02:34 +000068 CXCursor Parent;
69
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000070 /// The declaration that serves at the parent of any statement or
Argyrios Kyrtzidis52d87a62011-11-03 19:02:34 +000071 /// expression nodes.
Dmitri Gribenkod15bb302013-01-23 17:25:27 +000072 const Decl *StmtParent;
Argyrios Kyrtzidis52d87a62011-11-03 19:02:34 +000073
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000074 /// The visitor function.
Argyrios Kyrtzidis52d87a62011-11-03 19:02:34 +000075 CXCursorVisitor Visitor;
76
Argyrios Kyrtzidisda188de2012-09-01 18:27:30 +000077 PostChildrenVisitorTy PostChildrenVisitor;
78
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000079 /// The opaque client data, to be passed along to the visitor.
Argyrios Kyrtzidis52d87a62011-11-03 19:02:34 +000080 CXClientData ClientData;
81
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000082 /// Whether we should visit the preprocessing record entries last,
Argyrios Kyrtzidis52d87a62011-11-03 19:02:34 +000083 /// after visiting other declarations.
84 bool VisitPreprocessorLast;
85
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000086 /// Whether we should visit declarations or preprocessing record
Argyrios Kyrtzidis52d87a62011-11-03 19:02:34 +000087 /// entries that are #included inside the \arg RegionOfInterest.
88 bool VisitIncludedEntities;
89
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000090 /// When valid, a source range to which the cursor should restrict
Argyrios Kyrtzidis52d87a62011-11-03 19:02:34 +000091 /// its search.
92 SourceRange RegionOfInterest;
93
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000094 /// Whether we should only visit declarations and not preprocessing
Argyrios Kyrtzidis1ddb97ec2011-11-29 03:14:11 +000095 /// record entries.
96 bool VisitDeclsOnly;
97
Argyrios Kyrtzidis52d87a62011-11-03 19:02:34 +000098 // 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;
Argyrios Kyrtzidis463741a2011-11-16 08:58:57 +0000102 SmallVectorImpl<Decl *>::iterator *FileDI_current;
103 SmallVectorImpl<Decl *>::iterator FileDE_current;
Argyrios Kyrtzidis52d87a62011-11-03 19:02:34 +0000104
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
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000112 /// Determine whether this particular source range comes before, comes
Argyrios Kyrtzidis52d87a62011-11-03 19:02:34 +0000113 /// 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
Argyrios Kyrtzidis951f61f2013-03-08 20:42:33 +0000118 bool visitDeclsFromFileRegion(FileID File, unsigned Offset, unsigned Length);
Argyrios Kyrtzidis52d87a62011-11-03 19:02:34 +0000119
120 class SetParentRAII {
121 CXCursor &Parent;
Dmitri Gribenkod15bb302013-01-23 17:25:27 +0000122 const Decl *&StmtParent;
Argyrios Kyrtzidis52d87a62011-11-03 19:02:34 +0000123 CXCursor OldParent;
124
125 public:
Dmitri Gribenkod15bb302013-01-23 17:25:27 +0000126 SetParentRAII(CXCursor &Parent, const Decl *&StmtParent,
127 CXCursor NewParent)
Argyrios Kyrtzidis52d87a62011-11-03 19:02:34 +0000128 : 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
142public:
143 CursorVisitor(CXTranslationUnit TU, CXCursorVisitor Visitor,
144 CXClientData ClientData,
145 bool VisitPreprocessorLast,
146 bool VisitIncludedPreprocessingEntries = false,
Argyrios Kyrtzidis1ddb97ec2011-11-29 03:14:11 +0000147 SourceRange RegionOfInterest = SourceRange(),
Argyrios Kyrtzidisda188de2012-09-01 18:27:30 +0000148 bool VisitDeclsOnly = false,
Craig Topper69186e72014-06-08 08:38:04 +0000149 PostChildrenVisitorTy PostChildrenVisitor = nullptr)
Dmitri Gribenkoc22ea1c2013-01-26 18:53:38 +0000150 : TU(TU), AU(cxtu::getASTUnit(TU)),
Argyrios Kyrtzidisda188de2012-09-01 18:27:30 +0000151 Visitor(Visitor), PostChildrenVisitor(PostChildrenVisitor),
152 ClientData(ClientData),
Argyrios Kyrtzidis52d87a62011-11-03 19:02:34 +0000153 VisitPreprocessorLast(VisitPreprocessorLast),
154 VisitIncludedEntities(VisitIncludedPreprocessingEntries),
Argyrios Kyrtzidis1ddb97ec2011-11-29 03:14:11 +0000155 RegionOfInterest(RegionOfInterest),
156 VisitDeclsOnly(VisitDeclsOnly),
Craig Topper69186e72014-06-08 08:38:04 +0000157 DI_current(nullptr), FileDI_current(nullptr)
Argyrios Kyrtzidis52d87a62011-11-03 19:02:34 +0000158 {
159 Parent.kind = CXCursor_NoDeclFound;
Craig Topper69186e72014-06-08 08:38:04 +0000160 Parent.data[0] = nullptr;
161 Parent.data[1] = nullptr;
162 Parent.data[2] = nullptr;
163 StmtParent = nullptr;
Argyrios Kyrtzidis52d87a62011-11-03 19:02:34 +0000164 }
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
Dmitri Gribenkoc22ea1c2013-01-26 18:53:38 +0000174 ASTUnit *getASTUnit() const { return AU; }
Argyrios Kyrtzidis52d87a62011-11-03 19:02:34 +0000175 CXTranslationUnit getTU() const { return TU; }
176
177 bool Visit(CXCursor Cursor, bool CheckedRegionOfInterest = false);
178
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000179 /// Visit declarations and preprocessed entities for the file region
Argyrios Kyrtzidis52d87a62011-11-03 19:02:34 +0000180 /// designated by \see RegionOfInterest.
Argyrios Kyrtzidis951f61f2013-03-08 20:42:33 +0000181 bool visitFileRegion();
Argyrios Kyrtzidis52d87a62011-11-03 19:02:34 +0000182
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
Sergey Kalinichev8f3b1872015-11-15 13:48:32 +0000197 bool VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D);
Argyrios Kyrtzidis52d87a62011-11-03 19:02:34 +0000198 bool VisitTypeAliasDecl(TypeAliasDecl *D);
199 bool VisitAttributes(Decl *D);
200 bool VisitBlockDecl(BlockDecl *B);
201 bool VisitCXXRecordDecl(CXXRecordDecl *D);
Ted Kremenek03325582013-02-21 01:29:01 +0000202 Optional<bool> shouldVisitCursor(CXCursor C);
Argyrios Kyrtzidis52d87a62011-11-03 19:02:34 +0000203 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);
Douglas Gregor9bda6cf2015-07-07 03:58:14 +0000220 bool VisitObjCTypeParamDecl(ObjCTypeParamDecl *D);
Argyrios Kyrtzidis52d87a62011-11-03 19:02:34 +0000221 bool VisitObjCMethodDecl(ObjCMethodDecl *ND);
222 bool VisitObjCContainerDecl(ObjCContainerDecl *D);
223 bool VisitObjCCategoryDecl(ObjCCategoryDecl *ND);
224 bool VisitObjCProtocolDecl(ObjCProtocolDecl *PID);
225 bool VisitObjCPropertyDecl(ObjCPropertyDecl *PD);
Douglas Gregore9d95f12015-07-07 03:57:35 +0000226 bool VisitObjCTypeParamList(ObjCTypeParamList *typeParamList);
Argyrios Kyrtzidis52d87a62011-11-03 19:02:34 +0000227 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.
Argyrios Kyrtzidis52d87a62011-11-03 19:02:34 +0000232 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);
Olivier Goffart81978012016-06-09 16:15:55 +0000240 bool VisitStaticAssertDecl(StaticAssertDecl *D);
Olivier Goffartd211c642016-11-04 06:29:27 +0000241 bool VisitFriendDecl(FriendDecl *D);
242
Argyrios Kyrtzidis52d87a62011-11-03 19:02:34 +0000243 // 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);
Dmitri Gribenkoe8354062013-01-26 15:29:08 +0000266 void EnqueueWorkList(VisitorWorkList &WL, const Stmt *S);
267 LLVM_ATTRIBUTE_NOINLINE bool Visit(const Stmt *S);
Argyrios Kyrtzidise7c91042016-07-01 19:10:54 +0000268
269private:
270 Optional<bool> handleDeclForVisitation(const Decl *D);
Argyrios Kyrtzidis52d87a62011-11-03 19:02:34 +0000271};
272
Alexander Kornienkoab9db512015-06-22 23:07:51 +0000273}
274}
Argyrios Kyrtzidis52d87a62011-11-03 19:02:34 +0000275
276#endif
277