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_TOOLS_LIBCLANG_CURSORVISITOR_H
11#define LLVM_CLANG_TOOLS_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  const void *data[3];
37  CXCursor parent;
38  Kind K;
39  VisitorJob(CXCursor C, Kind k, const void *d1, const void *d2 = nullptr,
40             const void *d3 = nullptr)
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  const 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  bool visitDeclsFromFileRegion(FileID File, unsigned Offset, unsigned Length);
120
121  class SetParentRAII {
122    CXCursor &Parent;
123    const Decl *&StmtParent;
124    CXCursor OldParent;
125
126  public:
127    SetParentRAII(CXCursor &Parent, const Decl *&StmtParent,
128                  CXCursor NewParent)
129      : 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,
148                SourceRange RegionOfInterest = SourceRange(),
149                bool VisitDeclsOnly = false,
150                PostChildrenVisitorTy PostChildrenVisitor = nullptr)
151    : TU(TU), AU(cxtu::getASTUnit(TU)),
152      Visitor(Visitor), PostChildrenVisitor(PostChildrenVisitor),
153      ClientData(ClientData),
154      VisitPreprocessorLast(VisitPreprocessorLast),
155      VisitIncludedEntities(VisitIncludedPreprocessingEntries),
156      RegionOfInterest(RegionOfInterest),
157      VisitDeclsOnly(VisitDeclsOnly),
158      DI_current(nullptr), FileDI_current(nullptr)
159  {
160    Parent.kind = CXCursor_NoDeclFound;
161    Parent.data[0] = nullptr;
162    Parent.data[1] = nullptr;
163    Parent.data[2] = nullptr;
164    StmtParent = nullptr;
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
175  ASTUnit *getASTUnit() const { return AU; }
176  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  bool 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 VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D);
199  bool VisitTypeAliasDecl(TypeAliasDecl *D);
200  bool VisitAttributes(Decl *D);
201  bool VisitBlockDecl(BlockDecl *B);
202  bool VisitCXXRecordDecl(CXXRecordDecl *D);
203  Optional<bool> shouldVisitCursor(CXCursor C);
204  bool VisitDeclContext(DeclContext *DC);
205  bool VisitTranslationUnitDecl(TranslationUnitDecl *D);
206  bool VisitTypedefDecl(TypedefDecl *D);
207  bool VisitTagDecl(TagDecl *D);
208  bool VisitClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl *D);
209  bool VisitClassTemplatePartialSpecializationDecl(
210                                     ClassTemplatePartialSpecializationDecl *D);
211  bool VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
212  bool VisitEnumConstantDecl(EnumConstantDecl *D);
213  bool VisitDeclaratorDecl(DeclaratorDecl *DD);
214  bool VisitFunctionDecl(FunctionDecl *ND);
215  bool VisitFieldDecl(FieldDecl *D);
216  bool VisitVarDecl(VarDecl *);
217  bool VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
218  bool VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
219  bool VisitClassTemplateDecl(ClassTemplateDecl *D);
220  bool VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
221  bool VisitObjCTypeParamDecl(ObjCTypeParamDecl *D);
222  bool VisitObjCMethodDecl(ObjCMethodDecl *ND);
223  bool VisitObjCContainerDecl(ObjCContainerDecl *D);
224  bool VisitObjCCategoryDecl(ObjCCategoryDecl *ND);
225  bool VisitObjCProtocolDecl(ObjCProtocolDecl *PID);
226  bool VisitObjCPropertyDecl(ObjCPropertyDecl *PD);
227  bool VisitObjCTypeParamList(ObjCTypeParamList *typeParamList);
228  bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
229  bool VisitObjCImplDecl(ObjCImplDecl *D);
230  bool VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
231  bool VisitObjCImplementationDecl(ObjCImplementationDecl *D);
232  // FIXME: ObjCCompatibleAliasDecl requires aliased-class locations.
233  bool VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PD);
234  bool VisitLinkageSpecDecl(LinkageSpecDecl *D);
235  bool VisitNamespaceDecl(NamespaceDecl *D);
236  bool VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
237  bool VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
238  bool VisitUsingDecl(UsingDecl *D);
239  bool VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
240  bool VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
241
242  // Name visitor
243  bool VisitDeclarationNameInfo(DeclarationNameInfo Name);
244  bool VisitNestedNameSpecifier(NestedNameSpecifier *NNS, SourceRange Range);
245  bool VisitNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS);
246
247  // Template visitors
248  bool VisitTemplateParameters(const TemplateParameterList *Params);
249  bool VisitTemplateName(TemplateName Name, SourceLocation Loc);
250  bool VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL);
251
252  // Type visitors
253#define ABSTRACT_TYPELOC(CLASS, PARENT)
254#define TYPELOC(CLASS, PARENT) \
255  bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc);
256#include "clang/AST/TypeLocNodes.def"
257
258  bool VisitTagTypeLoc(TagTypeLoc TL);
259  bool VisitArrayTypeLoc(ArrayTypeLoc TL);
260  bool VisitFunctionTypeLoc(FunctionTypeLoc TL, bool SkipResultType = false);
261
262  // Data-recursive visitor functions.
263  bool IsInRegionOfInterest(CXCursor C);
264  bool RunVisitorWorkList(VisitorWorkList &WL);
265  void EnqueueWorkList(VisitorWorkList &WL, const Stmt *S);
266  LLVM_ATTRIBUTE_NOINLINE bool Visit(const Stmt *S);
267};
268
269}
270}
271
272#endif
273
274