CursorVisitor.h revision 76dd1d91692bc8ca2a0f8e74a663ca2f191e2104
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 "Index_Internal.h"
14#include "CXCursor.h"
15#include "CXTranslationUnit.h"
16
17#include "clang/AST/DeclVisitor.h"
18#include "clang/AST/TypeLocVisitor.h"
19
20namespace clang {
21  class PreprocessingRecord;
22  class ASTUnit;
23
24namespace cxcursor {
25
26class VisitorJob {
27public:
28  enum Kind { DeclVisitKind, StmtVisitKind, MemberExprPartsKind,
29              TypeLocVisitKind, OverloadExprPartsKind,
30              DeclRefExprPartsKind, LabelRefVisitKind,
31              ExplicitTemplateArgsVisitKind,
32              NestedNameSpecifierLocVisitKind,
33              DeclarationNameInfoVisitKind,
34              MemberRefVisitKind, SizeOfPackExprPartsKind,
35              LambdaExprPartsKind, PostChildrenVisitKind };
36protected:
37  void *data[3];
38  CXCursor parent;
39  Kind K;
40  VisitorJob(CXCursor C, Kind k, void *d1, void *d2 = 0, void *d3 = 0)
41    : 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; }
49};
50
51typedef SmallVector<VisitorJob, 10> VisitorWorkList;
52
53// Cursor visitor.
54class CursorVisitor : public DeclVisitor<CursorVisitor, bool>,
55                      public TypeLocVisitor<CursorVisitor, bool>
56{
57public:
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:
64  /// \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.
73  Decl *StmtParent;
74
75  /// \brief The visitor function.
76  CXCursorVisitor Visitor;
77
78  PostChildrenVisitorTy PostChildrenVisitor;
79
80  /// \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
95  /// \brief Whether we should only visit declarations and not preprocessing
96  /// record entries.
97  bool VisitDeclsOnly;
98
99  // 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;
103  SmallVectorImpl<Decl *>::iterator *FileDI_current;
104  SmallVectorImpl<Decl *>::iterator FileDE_current;
105
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;
123    Decl *&StmtParent;
124    CXCursor OldParent;
125
126  public:
127    SetParentRAII(CXCursor &Parent, Decl *&StmtParent, CXCursor NewParent)
128      : 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,
147                SourceRange RegionOfInterest = SourceRange(),
148                bool VisitDeclsOnly = false,
149                PostChildrenVisitorTy PostChildrenVisitor = 0)
150    : TU(TU), AU(static_cast<ASTUnit*>(TU->TUData)),
151      Visitor(Visitor), PostChildrenVisitor(PostChildrenVisitor),
152      ClientData(ClientData),
153      VisitPreprocessorLast(VisitPreprocessorLast),
154      VisitIncludedEntities(VisitIncludedPreprocessingEntries),
155      RegionOfInterest(RegionOfInterest),
156      VisitDeclsOnly(VisitDeclsOnly),
157      DI_current(0), FileDI_current(0)
158  {
159    Parent.kind = CXCursor_NoDeclFound;
160    Parent.data[0] = 0;
161    Parent.data[1] = 0;
162    Parent.data[2] = 0;
163    StmtParent = 0;
164  }
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
174  ASTUnit *getASTUnit() const { return static_cast<ASTUnit*>(TU->TUData); }
175  CXTranslationUnit getTU() const { return TU; }
176
177  bool Visit(CXCursor Cursor, bool CheckedRegionOfInterest = false);
178
179  /// \brief Visit declarations and preprocessed entities for the file region
180  /// designated by \see RegionOfInterest.
181  void visitFileRegion();
182
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
197  bool VisitTypeAliasDecl(TypeAliasDecl *D);
198  bool VisitAttributes(Decl *D);
199  bool VisitBlockDecl(BlockDecl *B);
200  bool VisitCXXRecordDecl(CXXRecordDecl *D);
201  llvm::Optional<bool> shouldVisitCursor(CXCursor C);
202  bool VisitDeclContext(DeclContext *DC);
203  bool VisitTranslationUnitDecl(TranslationUnitDecl *D);
204  bool VisitTypedefDecl(TypedefDecl *D);
205  bool VisitTagDecl(TagDecl *D);
206  bool VisitClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl *D);
207  bool VisitClassTemplatePartialSpecializationDecl(
208                                     ClassTemplatePartialSpecializationDecl *D);
209  bool VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
210  bool VisitEnumConstantDecl(EnumConstantDecl *D);
211  bool VisitDeclaratorDecl(DeclaratorDecl *DD);
212  bool VisitFunctionDecl(FunctionDecl *ND);
213  bool VisitFieldDecl(FieldDecl *D);
214  bool VisitVarDecl(VarDecl *);
215  bool VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
216  bool VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
217  bool VisitClassTemplateDecl(ClassTemplateDecl *D);
218  bool VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
219  bool VisitObjCMethodDecl(ObjCMethodDecl *ND);
220  bool VisitObjCContainerDecl(ObjCContainerDecl *D);
221  bool VisitObjCCategoryDecl(ObjCCategoryDecl *ND);
222  bool VisitObjCProtocolDecl(ObjCProtocolDecl *PID);
223  bool VisitObjCPropertyDecl(ObjCPropertyDecl *PD);
224  bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
225  bool VisitObjCImplDecl(ObjCImplDecl *D);
226  bool VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
227  bool VisitObjCImplementationDecl(ObjCImplementationDecl *D);
228  // FIXME: ObjCCompatibleAliasDecl requires aliased-class locations.
229  bool VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PD);
230  bool VisitLinkageSpecDecl(LinkageSpecDecl *D);
231  bool VisitNamespaceDecl(NamespaceDecl *D);
232  bool VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
233  bool VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
234  bool VisitUsingDecl(UsingDecl *D);
235  bool VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
236  bool VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
237
238  // Name visitor
239  bool VisitDeclarationNameInfo(DeclarationNameInfo Name);
240  bool VisitNestedNameSpecifier(NestedNameSpecifier *NNS, SourceRange Range);
241  bool VisitNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS);
242
243  // Template visitors
244  bool VisitTemplateParameters(const TemplateParameterList *Params);
245  bool VisitTemplateName(TemplateName Name, SourceLocation Loc);
246  bool VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL);
247
248  // Type visitors
249#define ABSTRACT_TYPELOC(CLASS, PARENT)
250#define TYPELOC(CLASS, PARENT) \
251  bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc);
252#include "clang/AST/TypeLocNodes.def"
253
254  bool VisitTagTypeLoc(TagTypeLoc TL);
255  bool VisitArrayTypeLoc(ArrayTypeLoc TL);
256  bool VisitFunctionTypeLoc(FunctionTypeLoc TL, bool SkipResultType = false);
257
258  // Data-recursive visitor functions.
259  bool IsInRegionOfInterest(CXCursor C);
260  bool RunVisitorWorkList(VisitorWorkList &WL);
261  void EnqueueWorkList(VisitorWorkList &WL, Stmt *S);
262  LLVM_ATTRIBUTE_NOINLINE bool Visit(Stmt *S);
263};
264
265}
266}
267
268#endif
269
270