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 
19 namespace clang {
20   class PreprocessingRecord;
21   class ASTUnit;
22 
23 namespace cxcursor {
24 
25 class VisitorJob {
26 public:
27   enum Kind { DeclVisitKind, StmtVisitKind, MemberExprPartsKind,
28               TypeLocVisitKind, OverloadExprPartsKind,
29               DeclRefExprPartsKind, LabelRefVisitKind,
30               ExplicitTemplateArgsVisitKind,
31               NestedNameSpecifierLocVisitKind,
32               DeclarationNameInfoVisitKind,
33               MemberRefVisitKind, SizeOfPackExprPartsKind,
34               LambdaExprPartsKind, PostChildrenVisitKind };
35 protected:
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)
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; }
49 };
50 
51 typedef SmallVector<VisitorJob, 10> VisitorWorkList;
52 
53 // Cursor visitor.
54 class CursorVisitor : public DeclVisitor<CursorVisitor, bool>,
55                       public TypeLocVisitor<CursorVisitor, bool>
56 {
57 public:
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 
63 private:
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:
SetParentRAII(CXCursor & Parent,const Decl * & StmtParent,CXCursor NewParent)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 
~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 = nullptr)
TU(TU)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 
~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 AU; }
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   bool 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 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