CursorVisitor.h revision e397bf1bd90cfceb0166606ebcd2580b7671a828
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
91  // Cache of pre-allocated worklists for data-recursion walk of Stmts.
92  SmallVector<VisitorWorkList*, 5> WorkListFreeList;
93  SmallVector<VisitorWorkList*, 5> WorkListCache;
94
95  using DeclVisitor<CursorVisitor, bool>::Visit;
96  using TypeLocVisitor<CursorVisitor, bool>::Visit;
97
98  /// \brief Determine whether this particular source range comes before, comes
99  /// after, or overlaps the region of interest.
100  ///
101  /// \param R a half-open source range retrieved from the abstract syntax tree.
102  RangeComparisonResult CompareRegionOfInterest(SourceRange R);
103
104  void visitDeclsFromFileRegion(FileID File, unsigned Offset, unsigned Length);
105
106  class SetParentRAII {
107    CXCursor &Parent;
108    Decl *&StmtParent;
109    CXCursor OldParent;
110
111  public:
112    SetParentRAII(CXCursor &Parent, Decl *&StmtParent, CXCursor NewParent)
113      : Parent(Parent), StmtParent(StmtParent), OldParent(Parent)
114    {
115      Parent = NewParent;
116      if (clang_isDeclaration(Parent.kind))
117        StmtParent = getCursorDecl(Parent);
118    }
119
120    ~SetParentRAII() {
121      Parent = OldParent;
122      if (clang_isDeclaration(Parent.kind))
123        StmtParent = getCursorDecl(Parent);
124    }
125  };
126
127public:
128  CursorVisitor(CXTranslationUnit TU, CXCursorVisitor Visitor,
129                CXClientData ClientData,
130                bool VisitPreprocessorLast,
131                bool VisitIncludedPreprocessingEntries = false,
132                SourceRange RegionOfInterest = SourceRange())
133    : TU(TU), AU(static_cast<ASTUnit*>(TU->TUData)),
134      Visitor(Visitor), ClientData(ClientData),
135      VisitPreprocessorLast(VisitPreprocessorLast),
136      VisitIncludedEntities(VisitIncludedPreprocessingEntries),
137      RegionOfInterest(RegionOfInterest), DI_current(0)
138  {
139    Parent.kind = CXCursor_NoDeclFound;
140    Parent.data[0] = 0;
141    Parent.data[1] = 0;
142    Parent.data[2] = 0;
143    StmtParent = 0;
144  }
145
146  ~CursorVisitor() {
147    // Free the pre-allocated worklists for data-recursion.
148    for (SmallVectorImpl<VisitorWorkList*>::iterator
149          I = WorkListCache.begin(), E = WorkListCache.end(); I != E; ++I) {
150      delete *I;
151    }
152  }
153
154  ASTUnit *getASTUnit() const { return static_cast<ASTUnit*>(TU->TUData); }
155  CXTranslationUnit getTU() const { return TU; }
156
157  bool Visit(CXCursor Cursor, bool CheckedRegionOfInterest = false);
158
159  /// \brief Visit declarations and preprocessed entities for the file region
160  /// designated by \see RegionOfInterest.
161  void visitFileRegion();
162
163  bool visitPreprocessedEntitiesInRegion();
164
165  bool shouldVisitIncludedEntities() const {
166    return VisitIncludedEntities;
167  }
168
169  template<typename InputIterator>
170  bool visitPreprocessedEntities(InputIterator First, InputIterator Last,
171                                 PreprocessingRecord &PPRec,
172                                 FileID FID = FileID());
173
174  bool VisitChildren(CXCursor Parent);
175
176  // Declaration visitors
177  bool VisitTypeAliasDecl(TypeAliasDecl *D);
178  bool VisitAttributes(Decl *D);
179  bool VisitBlockDecl(BlockDecl *B);
180  bool VisitCXXRecordDecl(CXXRecordDecl *D);
181  llvm::Optional<bool> shouldVisitCursor(CXCursor C);
182  bool VisitDeclContext(DeclContext *DC);
183  bool VisitTranslationUnitDecl(TranslationUnitDecl *D);
184  bool VisitTypedefDecl(TypedefDecl *D);
185  bool VisitTagDecl(TagDecl *D);
186  bool VisitClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl *D);
187  bool VisitClassTemplatePartialSpecializationDecl(
188                                     ClassTemplatePartialSpecializationDecl *D);
189  bool VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
190  bool VisitEnumConstantDecl(EnumConstantDecl *D);
191  bool VisitDeclaratorDecl(DeclaratorDecl *DD);
192  bool VisitFunctionDecl(FunctionDecl *ND);
193  bool VisitFieldDecl(FieldDecl *D);
194  bool VisitVarDecl(VarDecl *);
195  bool VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
196  bool VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
197  bool VisitClassTemplateDecl(ClassTemplateDecl *D);
198  bool VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
199  bool VisitObjCMethodDecl(ObjCMethodDecl *ND);
200  bool VisitObjCContainerDecl(ObjCContainerDecl *D);
201  bool VisitObjCCategoryDecl(ObjCCategoryDecl *ND);
202  bool VisitObjCProtocolDecl(ObjCProtocolDecl *PID);
203  bool VisitObjCPropertyDecl(ObjCPropertyDecl *PD);
204  bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
205  bool VisitObjCImplDecl(ObjCImplDecl *D);
206  bool VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
207  bool VisitObjCImplementationDecl(ObjCImplementationDecl *D);
208  // FIXME: ObjCCompatibleAliasDecl requires aliased-class locations.
209  bool VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D);
210  bool VisitObjCClassDecl(ObjCClassDecl *D);
211  bool VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PD);
212  bool VisitLinkageSpecDecl(LinkageSpecDecl *D);
213  bool VisitNamespaceDecl(NamespaceDecl *D);
214  bool VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
215  bool VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
216  bool VisitUsingDecl(UsingDecl *D);
217  bool VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
218  bool VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
219
220  // Name visitor
221  bool VisitDeclarationNameInfo(DeclarationNameInfo Name);
222  bool VisitNestedNameSpecifier(NestedNameSpecifier *NNS, SourceRange Range);
223  bool VisitNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS);
224
225  // Template visitors
226  bool VisitTemplateParameters(const TemplateParameterList *Params);
227  bool VisitTemplateName(TemplateName Name, SourceLocation Loc);
228  bool VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL);
229
230  // Type visitors
231#define ABSTRACT_TYPELOC(CLASS, PARENT)
232#define TYPELOC(CLASS, PARENT) \
233  bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc);
234#include "clang/AST/TypeLocNodes.def"
235
236  bool VisitTagTypeLoc(TagTypeLoc TL);
237  bool VisitArrayTypeLoc(ArrayTypeLoc TL);
238  bool VisitFunctionTypeLoc(FunctionTypeLoc TL, bool SkipResultType = false);
239
240  // Data-recursive visitor functions.
241  bool IsInRegionOfInterest(CXCursor C);
242  bool RunVisitorWorkList(VisitorWorkList &WL);
243  void EnqueueWorkList(VisitorWorkList &WL, Stmt *S);
244  LLVM_ATTRIBUTE_NOINLINE bool Visit(Stmt *S);
245};
246
247}
248}
249
250#endif
251
252