summaryrefslogtreecommitdiffstats
path: root/tools/libclang/CursorVisitor.h
blob: 88b70a490eb73a51478452257deac5309643ae46 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
//===- CursorVisitor.h - CursorVisitor interface --------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_LIBCLANG_CURSORVISITOR_H
#define LLVM_CLANG_LIBCLANG_CURSORVISITOR_H

#include "Index_Internal.h"
#include "CXCursor.h"
#include "CXTranslationUnit.h"

#include "clang/AST/DeclVisitor.h"
#include "clang/AST/TypeLocVisitor.h"

namespace clang {
  class PreprocessingRecord;
  class ASTUnit;

namespace cxcursor {

class VisitorJob {
public:
  enum Kind { DeclVisitKind, StmtVisitKind, MemberExprPartsKind,
              TypeLocVisitKind, OverloadExprPartsKind,
              DeclRefExprPartsKind, LabelRefVisitKind,
              ExplicitTemplateArgsVisitKind,
              NestedNameSpecifierLocVisitKind,
              DeclarationNameInfoVisitKind,
              MemberRefVisitKind, SizeOfPackExprPartsKind,
              LambdaExprPartsKind };
protected:
  void *data[3];
  CXCursor parent;
  Kind K;
  VisitorJob(CXCursor C, Kind k, void *d1, void *d2 = 0, void *d3 = 0)
    : parent(C), K(k) {
    data[0] = d1;
    data[1] = d2;
    data[2] = d3;
  }
public:
  Kind getKind() const { return K; }
  const CXCursor &getParent() const { return parent; }
  static bool classof(VisitorJob *VJ) { return true; }
};
  
typedef SmallVector<VisitorJob, 10> VisitorWorkList;

// Cursor visitor.
class CursorVisitor : public DeclVisitor<CursorVisitor, bool>,
                      public TypeLocVisitor<CursorVisitor, bool>
{
  /// \brief The translation unit we are traversing.
  CXTranslationUnit TU;
  ASTUnit *AU;

  /// \brief The parent cursor whose children we are traversing.
  CXCursor Parent;

  /// \brief The declaration that serves at the parent of any statement or
  /// expression nodes.
  Decl *StmtParent;

  /// \brief The visitor function.
  CXCursorVisitor Visitor;

  /// \brief The opaque client data, to be passed along to the visitor.
  CXClientData ClientData;

  /// \brief Whether we should visit the preprocessing record entries last, 
  /// after visiting other declarations.
  bool VisitPreprocessorLast;

  /// \brief Whether we should visit declarations or preprocessing record
  /// entries that are #included inside the \arg RegionOfInterest.
  bool VisitIncludedEntities;
  
  /// \brief When valid, a source range to which the cursor should restrict
  /// its search.
  SourceRange RegionOfInterest;

  /// \brief Whether we should only visit declarations and not preprocessing
  /// record entries.
  bool VisitDeclsOnly;

  // FIXME: Eventually remove.  This part of a hack to support proper
  // iteration over all Decls contained lexically within an ObjC container.
  DeclContext::decl_iterator *DI_current;
  DeclContext::decl_iterator DE_current;
  SmallVectorImpl<Decl *>::iterator *FileDI_current;
  SmallVectorImpl<Decl *>::iterator FileDE_current;

  // Cache of pre-allocated worklists for data-recursion walk of Stmts.
  SmallVector<VisitorWorkList*, 5> WorkListFreeList;
  SmallVector<VisitorWorkList*, 5> WorkListCache;

  using DeclVisitor<CursorVisitor, bool>::Visit;
  using TypeLocVisitor<CursorVisitor, bool>::Visit;

  /// \brief Determine whether this particular source range comes before, comes
  /// after, or overlaps the region of interest.
  ///
  /// \param R a half-open source range retrieved from the abstract syntax tree.
  RangeComparisonResult CompareRegionOfInterest(SourceRange R);

  void visitDeclsFromFileRegion(FileID File, unsigned Offset, unsigned Length);

  class SetParentRAII {
    CXCursor &Parent;
    Decl *&StmtParent;
    CXCursor OldParent;

  public:
    SetParentRAII(CXCursor &Parent, Decl *&StmtParent, CXCursor NewParent)
      : Parent(Parent), StmtParent(StmtParent), OldParent(Parent)
    {
      Parent = NewParent;
      if (clang_isDeclaration(Parent.kind))
        StmtParent = getCursorDecl(Parent);
    }

    ~SetParentRAII() {
      Parent = OldParent;
      if (clang_isDeclaration(Parent.kind))
        StmtParent = getCursorDecl(Parent);
    }
  };

public:
  CursorVisitor(CXTranslationUnit TU, CXCursorVisitor Visitor,
                CXClientData ClientData,
                bool VisitPreprocessorLast,
                bool VisitIncludedPreprocessingEntries = false,
                SourceRange RegionOfInterest = SourceRange(),
                bool VisitDeclsOnly = false)
    : TU(TU), AU(static_cast<ASTUnit*>(TU->TUData)),
      Visitor(Visitor), ClientData(ClientData),
      VisitPreprocessorLast(VisitPreprocessorLast),
      VisitIncludedEntities(VisitIncludedPreprocessingEntries),
      RegionOfInterest(RegionOfInterest),
      VisitDeclsOnly(VisitDeclsOnly),
      DI_current(0), FileDI_current(0)
  {
    Parent.kind = CXCursor_NoDeclFound;
    Parent.data[0] = 0;
    Parent.data[1] = 0;
    Parent.data[2] = 0;
    StmtParent = 0;
  }

  ~CursorVisitor() {
    // Free the pre-allocated worklists for data-recursion.
    for (SmallVectorImpl<VisitorWorkList*>::iterator
          I = WorkListCache.begin(), E = WorkListCache.end(); I != E; ++I) {
      delete *I;
    }
  }

  ASTUnit *getASTUnit() const { return static_cast<ASTUnit*>(TU->TUData); }
  CXTranslationUnit getTU() const { return TU; }

  bool Visit(CXCursor Cursor, bool CheckedRegionOfInterest = false);

  /// \brief Visit declarations and preprocessed entities for the file region
  /// designated by \see RegionOfInterest.
  void visitFileRegion();
  
  bool visitPreprocessedEntitiesInRegion();

  bool shouldVisitIncludedEntities() const {
    return VisitIncludedEntities;
  }

  template<typename InputIterator>
  bool visitPreprocessedEntities(InputIterator First, InputIterator Last,
                                 PreprocessingRecord &PPRec,
                                 FileID FID = FileID());

  bool VisitChildren(CXCursor Parent);

  // Declaration visitors
  bool VisitTypeAliasDecl(TypeAliasDecl *D);
  bool VisitAttributes(Decl *D);
  bool VisitBlockDecl(BlockDecl *B);
  bool VisitCXXRecordDecl(CXXRecordDecl *D);
  llvm::Optional<bool> shouldVisitCursor(CXCursor C);
  bool VisitDeclContext(DeclContext *DC);
  bool VisitTranslationUnitDecl(TranslationUnitDecl *D);
  bool VisitTypedefDecl(TypedefDecl *D);
  bool VisitTagDecl(TagDecl *D);
  bool VisitClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl *D);
  bool VisitClassTemplatePartialSpecializationDecl(
                                     ClassTemplatePartialSpecializationDecl *D);
  bool VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
  bool VisitEnumConstantDecl(EnumConstantDecl *D);
  bool VisitDeclaratorDecl(DeclaratorDecl *DD);
  bool VisitFunctionDecl(FunctionDecl *ND);
  bool VisitFieldDecl(FieldDecl *D);
  bool VisitVarDecl(VarDecl *);
  bool VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
  bool VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
  bool VisitClassTemplateDecl(ClassTemplateDecl *D);
  bool VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
  bool VisitObjCMethodDecl(ObjCMethodDecl *ND);
  bool VisitObjCContainerDecl(ObjCContainerDecl *D);
  bool VisitObjCCategoryDecl(ObjCCategoryDecl *ND);
  bool VisitObjCProtocolDecl(ObjCProtocolDecl *PID);
  bool VisitObjCPropertyDecl(ObjCPropertyDecl *PD);
  bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
  bool VisitObjCImplDecl(ObjCImplDecl *D);
  bool VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
  bool VisitObjCImplementationDecl(ObjCImplementationDecl *D);
  // FIXME: ObjCCompatibleAliasDecl requires aliased-class locations.
  bool VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PD);
  bool VisitLinkageSpecDecl(LinkageSpecDecl *D);
  bool VisitNamespaceDecl(NamespaceDecl *D);
  bool VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
  bool VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
  bool VisitUsingDecl(UsingDecl *D);
  bool VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
  bool VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
  
  // Name visitor
  bool VisitDeclarationNameInfo(DeclarationNameInfo Name);
  bool VisitNestedNameSpecifier(NestedNameSpecifier *NNS, SourceRange Range);
  bool VisitNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS);
  
  // Template visitors
  bool VisitTemplateParameters(const TemplateParameterList *Params);
  bool VisitTemplateName(TemplateName Name, SourceLocation Loc);
  bool VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL);
  
  // Type visitors
#define ABSTRACT_TYPELOC(CLASS, PARENT)
#define TYPELOC(CLASS, PARENT) \
  bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc);
#include "clang/AST/TypeLocNodes.def"

  bool VisitTagTypeLoc(TagTypeLoc TL);
  bool VisitArrayTypeLoc(ArrayTypeLoc TL);
  bool VisitFunctionTypeLoc(FunctionTypeLoc TL, bool SkipResultType = false);

  // Data-recursive visitor functions.
  bool IsInRegionOfInterest(CXCursor C);
  bool RunVisitorWorkList(VisitorWorkList &WL);
  void EnqueueWorkList(VisitorWorkList &WL, Stmt *S);
  LLVM_ATTRIBUTE_NOINLINE bool Visit(Stmt *S);
};

}
}

#endif