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