blob: 38b7f334ada9e9e8269962e1367a20d3fb98f5b4 [file] [log] [blame]
Nick Lewycky76dd1d92012-10-29 06:03:58 +00001//===- CursorVisitor.h - CursorVisitor interface ----------------*- C++ -*-===//
Argyrios Kyrtzidise397bf12011-11-03 19:02:34 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef LLVM_CLANG_LIBCLANG_CURSORVISITOR_H
11#define LLVM_CLANG_LIBCLANG_CURSORVISITOR_H
12
Argyrios Kyrtzidise397bf12011-11-03 19:02:34 +000013#include "CXCursor.h"
14#include "CXTranslationUnit.h"
Chandler Carruthf59edb92012-12-04 09:25:21 +000015#include "Index_Internal.h"
Argyrios Kyrtzidise397bf12011-11-03 19:02:34 +000016#include "clang/AST/DeclVisitor.h"
17#include "clang/AST/TypeLocVisitor.h"
18
19namespace clang {
20 class PreprocessingRecord;
21 class ASTUnit;
22
23namespace cxcursor {
24
25class VisitorJob {
26public:
27 enum Kind { DeclVisitKind, StmtVisitKind, MemberExprPartsKind,
28 TypeLocVisitKind, OverloadExprPartsKind,
29 DeclRefExprPartsKind, LabelRefVisitKind,
30 ExplicitTemplateArgsVisitKind,
31 NestedNameSpecifierLocVisitKind,
32 DeclarationNameInfoVisitKind,
Douglas Gregor011d8b92012-02-15 00:54:55 +000033 MemberRefVisitKind, SizeOfPackExprPartsKind,
Argyrios Kyrtzidisd579dd52012-09-01 18:27:30 +000034 LambdaExprPartsKind, PostChildrenVisitKind };
Argyrios Kyrtzidise397bf12011-11-03 19:02:34 +000035protected:
Dmitri Gribenkoff74f962013-01-26 15:29:08 +000036 const void *data[3];
Argyrios Kyrtzidise397bf12011-11-03 19:02:34 +000037 CXCursor parent;
38 Kind K;
Dmitri Gribenkoff74f962013-01-26 15:29:08 +000039 VisitorJob(CXCursor C, Kind k, const void *d1, const void *d2 = 0,
40 const void *d3 = 0)
Argyrios Kyrtzidise397bf12011-11-03 19:02:34 +000041 : parent(C), K(k) {
42 data[0] = d1;
43 data[1] = d2;
44 data[2] = d3;
45 }
46public:
47 Kind getKind() const { return K; }
48 const CXCursor &getParent() const { return parent; }
Argyrios Kyrtzidise397bf12011-11-03 19:02:34 +000049};
50
51typedef SmallVector<VisitorJob, 10> VisitorWorkList;
52
53// Cursor visitor.
54class CursorVisitor : public DeclVisitor<CursorVisitor, bool>,
55 public TypeLocVisitor<CursorVisitor, bool>
56{
Argyrios Kyrtzidisd579dd52012-09-01 18:27:30 +000057public:
58 /// \brief Callback called after child nodes of a cursor have been visited.
59 /// Return true to break visitation or false to continue.
60 typedef bool (*PostChildrenVisitorTy)(CXCursor cursor,
61 CXClientData client_data);
62
63private:
Argyrios Kyrtzidise397bf12011-11-03 19:02:34 +000064 /// \brief The translation unit we are traversing.
65 CXTranslationUnit TU;
66 ASTUnit *AU;
67
68 /// \brief The parent cursor whose children we are traversing.
69 CXCursor Parent;
70
71 /// \brief The declaration that serves at the parent of any statement or
72 /// expression nodes.
Dmitri Gribenkoe22339c2013-01-23 17:25:27 +000073 const Decl *StmtParent;
Argyrios Kyrtzidise397bf12011-11-03 19:02:34 +000074
75 /// \brief The visitor function.
76 CXCursorVisitor Visitor;
77
Argyrios Kyrtzidisd579dd52012-09-01 18:27:30 +000078 PostChildrenVisitorTy PostChildrenVisitor;
79
Argyrios Kyrtzidise397bf12011-11-03 19:02:34 +000080 /// \brief The opaque client data, to be passed along to the visitor.
81 CXClientData ClientData;
82
83 /// \brief Whether we should visit the preprocessing record entries last,
84 /// after visiting other declarations.
85 bool VisitPreprocessorLast;
86
87 /// \brief Whether we should visit declarations or preprocessing record
88 /// entries that are #included inside the \arg RegionOfInterest.
89 bool VisitIncludedEntities;
90
91 /// \brief When valid, a source range to which the cursor should restrict
92 /// its search.
93 SourceRange RegionOfInterest;
94
Argyrios Kyrtzidisb49e7282011-11-29 03:14:11 +000095 /// \brief Whether we should only visit declarations and not preprocessing
96 /// record entries.
97 bool VisitDeclsOnly;
98
Argyrios Kyrtzidise397bf12011-11-03 19:02:34 +000099 // FIXME: Eventually remove. This part of a hack to support proper
100 // iteration over all Decls contained lexically within an ObjC container.
101 DeclContext::decl_iterator *DI_current;
102 DeclContext::decl_iterator DE_current;
Argyrios Kyrtzidis03ee2dd2011-11-16 08:58:57 +0000103 SmallVectorImpl<Decl *>::iterator *FileDI_current;
104 SmallVectorImpl<Decl *>::iterator FileDE_current;
Argyrios Kyrtzidise397bf12011-11-03 19:02:34 +0000105
106 // Cache of pre-allocated worklists for data-recursion walk of Stmts.
107 SmallVector<VisitorWorkList*, 5> WorkListFreeList;
108 SmallVector<VisitorWorkList*, 5> WorkListCache;
109
110 using DeclVisitor<CursorVisitor, bool>::Visit;
111 using TypeLocVisitor<CursorVisitor, bool>::Visit;
112
113 /// \brief Determine whether this particular source range comes before, comes
114 /// after, or overlaps the region of interest.
115 ///
116 /// \param R a half-open source range retrieved from the abstract syntax tree.
117 RangeComparisonResult CompareRegionOfInterest(SourceRange R);
118
119 void visitDeclsFromFileRegion(FileID File, unsigned Offset, unsigned Length);
120
121 class SetParentRAII {
122 CXCursor &Parent;
Dmitri Gribenkoe22339c2013-01-23 17:25:27 +0000123 const Decl *&StmtParent;
Argyrios Kyrtzidise397bf12011-11-03 19:02:34 +0000124 CXCursor OldParent;
125
126 public:
Dmitri Gribenkoe22339c2013-01-23 17:25:27 +0000127 SetParentRAII(CXCursor &Parent, const Decl *&StmtParent,
128 CXCursor NewParent)
Argyrios Kyrtzidise397bf12011-11-03 19:02:34 +0000129 : Parent(Parent), StmtParent(StmtParent), OldParent(Parent)
130 {
131 Parent = NewParent;
132 if (clang_isDeclaration(Parent.kind))
133 StmtParent = getCursorDecl(Parent);
134 }
135
136 ~SetParentRAII() {
137 Parent = OldParent;
138 if (clang_isDeclaration(Parent.kind))
139 StmtParent = getCursorDecl(Parent);
140 }
141 };
142
143public:
144 CursorVisitor(CXTranslationUnit TU, CXCursorVisitor Visitor,
145 CXClientData ClientData,
146 bool VisitPreprocessorLast,
147 bool VisitIncludedPreprocessingEntries = false,
Argyrios Kyrtzidisb49e7282011-11-29 03:14:11 +0000148 SourceRange RegionOfInterest = SourceRange(),
Argyrios Kyrtzidisd579dd52012-09-01 18:27:30 +0000149 bool VisitDeclsOnly = false,
150 PostChildrenVisitorTy PostChildrenVisitor = 0)
Dmitri Gribenko5694feb2013-01-26 18:53:38 +0000151 : TU(TU), AU(cxtu::getASTUnit(TU)),
Argyrios Kyrtzidisd579dd52012-09-01 18:27:30 +0000152 Visitor(Visitor), PostChildrenVisitor(PostChildrenVisitor),
153 ClientData(ClientData),
Argyrios Kyrtzidise397bf12011-11-03 19:02:34 +0000154 VisitPreprocessorLast(VisitPreprocessorLast),
155 VisitIncludedEntities(VisitIncludedPreprocessingEntries),
Argyrios Kyrtzidisb49e7282011-11-29 03:14:11 +0000156 RegionOfInterest(RegionOfInterest),
157 VisitDeclsOnly(VisitDeclsOnly),
158 DI_current(0), FileDI_current(0)
Argyrios Kyrtzidise397bf12011-11-03 19:02:34 +0000159 {
160 Parent.kind = CXCursor_NoDeclFound;
161 Parent.data[0] = 0;
162 Parent.data[1] = 0;
163 Parent.data[2] = 0;
164 StmtParent = 0;
165 }
166
167 ~CursorVisitor() {
168 // Free the pre-allocated worklists for data-recursion.
169 for (SmallVectorImpl<VisitorWorkList*>::iterator
170 I = WorkListCache.begin(), E = WorkListCache.end(); I != E; ++I) {
171 delete *I;
172 }
173 }
174
Dmitri Gribenko5694feb2013-01-26 18:53:38 +0000175 ASTUnit *getASTUnit() const { return AU; }
Argyrios Kyrtzidise397bf12011-11-03 19:02:34 +0000176 CXTranslationUnit getTU() const { return TU; }
177
178 bool Visit(CXCursor Cursor, bool CheckedRegionOfInterest = false);
179
180 /// \brief Visit declarations and preprocessed entities for the file region
181 /// designated by \see RegionOfInterest.
182 void visitFileRegion();
183
184 bool visitPreprocessedEntitiesInRegion();
185
186 bool shouldVisitIncludedEntities() const {
187 return VisitIncludedEntities;
188 }
189
190 template<typename InputIterator>
191 bool visitPreprocessedEntities(InputIterator First, InputIterator Last,
192 PreprocessingRecord &PPRec,
193 FileID FID = FileID());
194
195 bool VisitChildren(CXCursor Parent);
196
197 // Declaration visitors
198 bool VisitTypeAliasDecl(TypeAliasDecl *D);
199 bool VisitAttributes(Decl *D);
200 bool VisitBlockDecl(BlockDecl *B);
201 bool VisitCXXRecordDecl(CXXRecordDecl *D);
Ted Kremenek943f9092013-02-21 01:29:01 +0000202 Optional<bool> shouldVisitCursor(CXCursor C);
Argyrios Kyrtzidise397bf12011-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);
220 bool VisitObjCMethodDecl(ObjCMethodDecl *ND);
221 bool VisitObjCContainerDecl(ObjCContainerDecl *D);
222 bool VisitObjCCategoryDecl(ObjCCategoryDecl *ND);
223 bool VisitObjCProtocolDecl(ObjCProtocolDecl *PID);
224 bool VisitObjCPropertyDecl(ObjCPropertyDecl *PD);
225 bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
226 bool VisitObjCImplDecl(ObjCImplDecl *D);
227 bool VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
228 bool VisitObjCImplementationDecl(ObjCImplementationDecl *D);
229 // FIXME: ObjCCompatibleAliasDecl requires aliased-class locations.
Argyrios Kyrtzidise397bf12011-11-03 19:02:34 +0000230 bool VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PD);
231 bool VisitLinkageSpecDecl(LinkageSpecDecl *D);
232 bool VisitNamespaceDecl(NamespaceDecl *D);
233 bool VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
234 bool VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
235 bool VisitUsingDecl(UsingDecl *D);
236 bool VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
237 bool VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
238
239 // Name visitor
240 bool VisitDeclarationNameInfo(DeclarationNameInfo Name);
241 bool VisitNestedNameSpecifier(NestedNameSpecifier *NNS, SourceRange Range);
242 bool VisitNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS);
243
244 // Template visitors
245 bool VisitTemplateParameters(const TemplateParameterList *Params);
246 bool VisitTemplateName(TemplateName Name, SourceLocation Loc);
247 bool VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL);
248
249 // Type visitors
250#define ABSTRACT_TYPELOC(CLASS, PARENT)
251#define TYPELOC(CLASS, PARENT) \
252 bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc);
253#include "clang/AST/TypeLocNodes.def"
254
255 bool VisitTagTypeLoc(TagTypeLoc TL);
256 bool VisitArrayTypeLoc(ArrayTypeLoc TL);
257 bool VisitFunctionTypeLoc(FunctionTypeLoc TL, bool SkipResultType = false);
258
259 // Data-recursive visitor functions.
260 bool IsInRegionOfInterest(CXCursor C);
261 bool RunVisitorWorkList(VisitorWorkList &WL);
Dmitri Gribenkoff74f962013-01-26 15:29:08 +0000262 void EnqueueWorkList(VisitorWorkList &WL, const Stmt *S);
263 LLVM_ATTRIBUTE_NOINLINE bool Visit(const Stmt *S);
Argyrios Kyrtzidise397bf12011-11-03 19:02:34 +0000264};
265
266}
267}
268
269#endif
270