CursorVisitor.h revision f59edb96b2d0bfe612b732f19519ab84bb995bd4
1//===- CursorVisitor.h - CursorVisitor interface ----------------*- C++ -*-===//
2//
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
13#include "CXCursor.h"
14#include "CXTranslationUnit.h"
15#include "Index_Internal.h"
16#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,
33              MemberRefVisitKind, SizeOfPackExprPartsKind,
34              LambdaExprPartsKind, PostChildrenVisitKind };
35protected:
36  void *data[3];
37  CXCursor parent;
38  Kind K;
39  VisitorJob(CXCursor C, Kind k, void *d1, void *d2 = 0, void *d3 = 0)
40    : 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; }
48};
49
50typedef SmallVector<VisitorJob, 10> VisitorWorkList;
51
52// Cursor visitor.
53class CursorVisitor : public DeclVisitor<CursorVisitor, bool>,
54                      public TypeLocVisitor<CursorVisitor, bool>
55{
56public:
57  /// \brief Callback called after child nodes of a cursor have been visited.
58  /// Return true to break visitation or false to continue.
59  typedef bool (*PostChildrenVisitorTy)(CXCursor cursor,
60                                        CXClientData client_data);
61
62private:
63  /// \brief The translation unit we are traversing.
64  CXTranslationUnit TU;
65  ASTUnit *AU;
66
67  /// \brief The parent cursor whose children we are traversing.
68  CXCursor Parent;
69
70  /// \brief The declaration that serves at the parent of any statement or
71  /// expression nodes.
72  Decl *StmtParent;
73
74  /// \brief The visitor function.
75  CXCursorVisitor Visitor;
76
77  PostChildrenVisitorTy PostChildrenVisitor;
78
79  /// \brief The opaque client data, to be passed along to the visitor.
80  CXClientData ClientData;
81
82  /// \brief Whether we should visit the preprocessing record entries last,
83  /// after visiting other declarations.
84  bool VisitPreprocessorLast;
85
86  /// \brief Whether we should visit declarations or preprocessing record
87  /// entries that are #included inside the \arg RegionOfInterest.
88  bool VisitIncludedEntities;
89
90  /// \brief When valid, a source range to which the cursor should restrict
91  /// its search.
92  SourceRange RegionOfInterest;
93
94  /// \brief Whether we should only visit declarations and not preprocessing
95  /// record entries.
96  bool VisitDeclsOnly;
97
98  // 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;
102  SmallVectorImpl<Decl *>::iterator *FileDI_current;
103  SmallVectorImpl<Decl *>::iterator FileDE_current;
104
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
112  /// \brief Determine whether this particular source range comes before, comes
113  /// 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
118  void visitDeclsFromFileRegion(FileID File, unsigned Offset, unsigned Length);
119
120  class SetParentRAII {
121    CXCursor &Parent;
122    Decl *&StmtParent;
123    CXCursor OldParent;
124
125  public:
126    SetParentRAII(CXCursor &Parent, Decl *&StmtParent, CXCursor NewParent)
127      : Parent(Parent), StmtParent(StmtParent), OldParent(Parent)
128    {
129      Parent = NewParent;
130      if (clang_isDeclaration(Parent.kind))
131        StmtParent = getCursorDecl(Parent);
132    }
133
134    ~SetParentRAII() {
135      Parent = OldParent;
136      if (clang_isDeclaration(Parent.kind))
137        StmtParent = getCursorDecl(Parent);
138    }
139  };
140
141public:
142  CursorVisitor(CXTranslationUnit TU, CXCursorVisitor Visitor,
143                CXClientData ClientData,
144                bool VisitPreprocessorLast,
145                bool VisitIncludedPreprocessingEntries = false,
146                SourceRange RegionOfInterest = SourceRange(),
147                bool VisitDeclsOnly = false,
148                PostChildrenVisitorTy PostChildrenVisitor = 0)
149    : TU(TU), AU(static_cast<ASTUnit*>(TU->TUData)),
150      Visitor(Visitor), PostChildrenVisitor(PostChildrenVisitor),
151      ClientData(ClientData),
152      VisitPreprocessorLast(VisitPreprocessorLast),
153      VisitIncludedEntities(VisitIncludedPreprocessingEntries),
154      RegionOfInterest(RegionOfInterest),
155      VisitDeclsOnly(VisitDeclsOnly),
156      DI_current(0), FileDI_current(0)
157  {
158    Parent.kind = CXCursor_NoDeclFound;
159    Parent.data[0] = 0;
160    Parent.data[1] = 0;
161    Parent.data[2] = 0;
162    StmtParent = 0;
163  }
164
165  ~CursorVisitor() {
166    // Free the pre-allocated worklists for data-recursion.
167    for (SmallVectorImpl<VisitorWorkList*>::iterator
168          I = WorkListCache.begin(), E = WorkListCache.end(); I != E; ++I) {
169      delete *I;
170    }
171  }
172
173  ASTUnit *getASTUnit() const { return static_cast<ASTUnit*>(TU->TUData); }
174  CXTranslationUnit getTU() const { return TU; }
175
176  bool Visit(CXCursor Cursor, bool CheckedRegionOfInterest = false);
177
178  /// \brief Visit declarations and preprocessed entities for the file region
179  /// designated by \see RegionOfInterest.
180  void visitFileRegion();
181
182  bool visitPreprocessedEntitiesInRegion();
183
184  bool shouldVisitIncludedEntities() const {
185    return VisitIncludedEntities;
186  }
187
188  template<typename InputIterator>
189  bool visitPreprocessedEntities(InputIterator First, InputIterator Last,
190                                 PreprocessingRecord &PPRec,
191                                 FileID FID = FileID());
192
193  bool VisitChildren(CXCursor Parent);
194
195  // Declaration visitors
196  bool VisitTypeAliasDecl(TypeAliasDecl *D);
197  bool VisitAttributes(Decl *D);
198  bool VisitBlockDecl(BlockDecl *B);
199  bool VisitCXXRecordDecl(CXXRecordDecl *D);
200  llvm::Optional<bool> shouldVisitCursor(CXCursor C);
201  bool VisitDeclContext(DeclContext *DC);
202  bool VisitTranslationUnitDecl(TranslationUnitDecl *D);
203  bool VisitTypedefDecl(TypedefDecl *D);
204  bool VisitTagDecl(TagDecl *D);
205  bool VisitClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl *D);
206  bool VisitClassTemplatePartialSpecializationDecl(
207                                     ClassTemplatePartialSpecializationDecl *D);
208  bool VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
209  bool VisitEnumConstantDecl(EnumConstantDecl *D);
210  bool VisitDeclaratorDecl(DeclaratorDecl *DD);
211  bool VisitFunctionDecl(FunctionDecl *ND);
212  bool VisitFieldDecl(FieldDecl *D);
213  bool VisitVarDecl(VarDecl *);
214  bool VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
215  bool VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
216  bool VisitClassTemplateDecl(ClassTemplateDecl *D);
217  bool VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
218  bool VisitObjCMethodDecl(ObjCMethodDecl *ND);
219  bool VisitObjCContainerDecl(ObjCContainerDecl *D);
220  bool VisitObjCCategoryDecl(ObjCCategoryDecl *ND);
221  bool VisitObjCProtocolDecl(ObjCProtocolDecl *PID);
222  bool VisitObjCPropertyDecl(ObjCPropertyDecl *PD);
223  bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
224  bool VisitObjCImplDecl(ObjCImplDecl *D);
225  bool VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
226  bool VisitObjCImplementationDecl(ObjCImplementationDecl *D);
227  // FIXME: ObjCCompatibleAliasDecl requires aliased-class locations.
228  bool VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PD);
229  bool VisitLinkageSpecDecl(LinkageSpecDecl *D);
230  bool VisitNamespaceDecl(NamespaceDecl *D);
231  bool VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
232  bool VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
233  bool VisitUsingDecl(UsingDecl *D);
234  bool VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
235  bool VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
236
237  // Name visitor
238  bool VisitDeclarationNameInfo(DeclarationNameInfo Name);
239  bool VisitNestedNameSpecifier(NestedNameSpecifier *NNS, SourceRange Range);
240  bool VisitNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS);
241
242  // Template visitors
243  bool VisitTemplateParameters(const TemplateParameterList *Params);
244  bool VisitTemplateName(TemplateName Name, SourceLocation Loc);
245  bool VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL);
246
247  // Type visitors
248#define ABSTRACT_TYPELOC(CLASS, PARENT)
249#define TYPELOC(CLASS, PARENT) \
250  bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc);
251#include "clang/AST/TypeLocNodes.def"
252
253  bool VisitTagTypeLoc(TagTypeLoc TL);
254  bool VisitArrayTypeLoc(ArrayTypeLoc TL);
255  bool VisitFunctionTypeLoc(FunctionTypeLoc TL, bool SkipResultType = false);
256
257  // Data-recursive visitor functions.
258  bool IsInRegionOfInterest(CXCursor C);
259  bool RunVisitorWorkList(VisitorWorkList &WL);
260  void EnqueueWorkList(VisitorWorkList &WL, Stmt *S);
261  LLVM_ATTRIBUTE_NOINLINE bool Visit(Stmt *S);
262};
263
264}
265}
266
267#endif
268
269