• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
20 namespace clang {
21   class PreprocessingRecord;
22   class ASTUnit;
23 
24 namespace cxcursor {
25 
26 class VisitorJob {
27 public:
28   enum Kind { DeclVisitKind, StmtVisitKind, MemberExprPartsKind,
29               TypeLocVisitKind, OverloadExprPartsKind,
30               DeclRefExprPartsKind, LabelRefVisitKind,
31               ExplicitTemplateArgsVisitKind,
32               NestedNameSpecifierLocVisitKind,
33               DeclarationNameInfoVisitKind,
34               MemberRefVisitKind, SizeOfPackExprPartsKind,
35               LambdaExprPartsKind, PostChildrenVisitKind };
36 protected:
37   void *data[3];
38   CXCursor parent;
39   Kind K;
40   VisitorJob(CXCursor C, Kind k, void *d1, void *d2 = 0, void *d3 = 0)
parent(C)41     : parent(C), K(k) {
42     data[0] = d1;
43     data[1] = d2;
44     data[2] = d3;
45   }
46 public:
getKind()47   Kind getKind() const { return K; }
getParent()48   const CXCursor &getParent() const { return parent; }
classof(VisitorJob * VJ)49   static bool classof(VisitorJob *VJ) { return true; }
50 };
51 
52 typedef SmallVector<VisitorJob, 10> VisitorWorkList;
53 
54 // Cursor visitor.
55 class CursorVisitor : public DeclVisitor<CursorVisitor, bool>,
56                       public TypeLocVisitor<CursorVisitor, bool>
57 {
58 public:
59   /// \brief Callback called after child nodes of a cursor have been visited.
60   /// Return true to break visitation or false to continue.
61   typedef bool (*PostChildrenVisitorTy)(CXCursor cursor,
62                                         CXClientData client_data);
63 
64 private:
65   /// \brief The translation unit we are traversing.
66   CXTranslationUnit TU;
67   ASTUnit *AU;
68 
69   /// \brief The parent cursor whose children we are traversing.
70   CXCursor Parent;
71 
72   /// \brief The declaration that serves at the parent of any statement or
73   /// expression nodes.
74   Decl *StmtParent;
75 
76   /// \brief The visitor function.
77   CXCursorVisitor Visitor;
78 
79   PostChildrenVisitorTy PostChildrenVisitor;
80 
81   /// \brief The opaque client data, to be passed along to the visitor.
82   CXClientData ClientData;
83 
84   /// \brief Whether we should visit the preprocessing record entries last,
85   /// after visiting other declarations.
86   bool VisitPreprocessorLast;
87 
88   /// \brief Whether we should visit declarations or preprocessing record
89   /// entries that are #included inside the \arg RegionOfInterest.
90   bool VisitIncludedEntities;
91 
92   /// \brief When valid, a source range to which the cursor should restrict
93   /// its search.
94   SourceRange RegionOfInterest;
95 
96   /// \brief Whether we should only visit declarations and not preprocessing
97   /// record entries.
98   bool VisitDeclsOnly;
99 
100   // FIXME: Eventually remove.  This part of a hack to support proper
101   // iteration over all Decls contained lexically within an ObjC container.
102   DeclContext::decl_iterator *DI_current;
103   DeclContext::decl_iterator DE_current;
104   SmallVectorImpl<Decl *>::iterator *FileDI_current;
105   SmallVectorImpl<Decl *>::iterator FileDE_current;
106 
107   // Cache of pre-allocated worklists for data-recursion walk of Stmts.
108   SmallVector<VisitorWorkList*, 5> WorkListFreeList;
109   SmallVector<VisitorWorkList*, 5> WorkListCache;
110 
111   using DeclVisitor<CursorVisitor, bool>::Visit;
112   using TypeLocVisitor<CursorVisitor, bool>::Visit;
113 
114   /// \brief Determine whether this particular source range comes before, comes
115   /// after, or overlaps the region of interest.
116   ///
117   /// \param R a half-open source range retrieved from the abstract syntax tree.
118   RangeComparisonResult CompareRegionOfInterest(SourceRange R);
119 
120   void visitDeclsFromFileRegion(FileID File, unsigned Offset, unsigned Length);
121 
122   class SetParentRAII {
123     CXCursor &Parent;
124     Decl *&StmtParent;
125     CXCursor OldParent;
126 
127   public:
SetParentRAII(CXCursor & Parent,Decl * & StmtParent,CXCursor NewParent)128     SetParentRAII(CXCursor &Parent, Decl *&StmtParent, 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 
~SetParentRAII()136     ~SetParentRAII() {
137       Parent = OldParent;
138       if (clang_isDeclaration(Parent.kind))
139         StmtParent = getCursorDecl(Parent);
140     }
141   };
142 
143 public:
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 = 0)
TU(TU)151     : TU(TU), AU(static_cast<ASTUnit*>(TU->TUData)),
152       Visitor(Visitor), PostChildrenVisitor(PostChildrenVisitor),
153       ClientData(ClientData),
154       VisitPreprocessorLast(VisitPreprocessorLast),
155       VisitIncludedEntities(VisitIncludedPreprocessingEntries),
156       RegionOfInterest(RegionOfInterest),
157       VisitDeclsOnly(VisitDeclsOnly),
158       DI_current(0), FileDI_current(0)
159   {
160     Parent.kind = CXCursor_NoDeclFound;
161     Parent.data[0] = 0;
162     Parent.data[1] = 0;
163     Parent.data[2] = 0;
164     StmtParent = 0;
165   }
166 
~CursorVisitor()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 
getASTUnit()175   ASTUnit *getASTUnit() const { return static_cast<ASTUnit*>(TU->TUData); }
getTU()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   void visitFileRegion();
183 
184   bool visitPreprocessedEntitiesInRegion();
185 
shouldVisitIncludedEntities()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 VisitTypeAliasDecl(TypeAliasDecl *D);
199   bool VisitAttributes(Decl *D);
200   bool VisitBlockDecl(BlockDecl *B);
201   bool VisitCXXRecordDecl(CXXRecordDecl *D);
202   llvm::Optional<bool> shouldVisitCursor(CXCursor C);
203   bool VisitDeclContext(DeclContext *DC);
204   bool VisitTranslationUnitDecl(TranslationUnitDecl *D);
205   bool VisitTypedefDecl(TypedefDecl *D);
206   bool VisitTagDecl(TagDecl *D);
207   bool VisitClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl *D);
208   bool VisitClassTemplatePartialSpecializationDecl(
209                                      ClassTemplatePartialSpecializationDecl *D);
210   bool VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
211   bool VisitEnumConstantDecl(EnumConstantDecl *D);
212   bool VisitDeclaratorDecl(DeclaratorDecl *DD);
213   bool VisitFunctionDecl(FunctionDecl *ND);
214   bool VisitFieldDecl(FieldDecl *D);
215   bool VisitVarDecl(VarDecl *);
216   bool VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
217   bool VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
218   bool VisitClassTemplateDecl(ClassTemplateDecl *D);
219   bool VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
220   bool VisitObjCMethodDecl(ObjCMethodDecl *ND);
221   bool VisitObjCContainerDecl(ObjCContainerDecl *D);
222   bool VisitObjCCategoryDecl(ObjCCategoryDecl *ND);
223   bool VisitObjCProtocolDecl(ObjCProtocolDecl *PID);
224   bool VisitObjCPropertyDecl(ObjCPropertyDecl *PD);
225   bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
226   bool VisitObjCImplDecl(ObjCImplDecl *D);
227   bool VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
228   bool VisitObjCImplementationDecl(ObjCImplementationDecl *D);
229   // FIXME: ObjCCompatibleAliasDecl requires aliased-class locations.
230   bool VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PD);
231   bool VisitLinkageSpecDecl(LinkageSpecDecl *D);
232   bool VisitNamespaceDecl(NamespaceDecl *D);
233   bool VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
234   bool VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
235   bool VisitUsingDecl(UsingDecl *D);
236   bool VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
237   bool VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
238 
239   // Name visitor
240   bool VisitDeclarationNameInfo(DeclarationNameInfo Name);
241   bool VisitNestedNameSpecifier(NestedNameSpecifier *NNS, SourceRange Range);
242   bool VisitNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS);
243 
244   // Template visitors
245   bool VisitTemplateParameters(const TemplateParameterList *Params);
246   bool VisitTemplateName(TemplateName Name, SourceLocation Loc);
247   bool VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL);
248 
249   // Type visitors
250 #define ABSTRACT_TYPELOC(CLASS, PARENT)
251 #define TYPELOC(CLASS, PARENT) \
252   bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc);
253 #include "clang/AST/TypeLocNodes.def"
254 
255   bool VisitTagTypeLoc(TagTypeLoc TL);
256   bool VisitArrayTypeLoc(ArrayTypeLoc TL);
257   bool VisitFunctionTypeLoc(FunctionTypeLoc TL, bool SkipResultType = false);
258 
259   // Data-recursive visitor functions.
260   bool IsInRegionOfInterest(CXCursor C);
261   bool RunVisitorWorkList(VisitorWorkList &WL);
262   void EnqueueWorkList(VisitorWorkList &WL, Stmt *S);
263   LLVM_ATTRIBUTE_NOINLINE bool Visit(Stmt *S);
264 };
265 
266 }
267 }
268 
269 #endif
270 
271