1 //===- CursorVisitor.h - CursorVisitor interface ----------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLVM_CLANG_TOOLS_LIBCLANG_CURSORVISITOR_H
10 #define LLVM_CLANG_TOOLS_LIBCLANG_CURSORVISITOR_H
11 
12 #include "CXCursor.h"
13 #include "CXTranslationUnit.h"
14 #include "Index_Internal.h"
15 #include "clang/AST/DeclVisitor.h"
16 #include "clang/AST/TypeLocVisitor.h"
17 
18 namespace clang {
19 class PreprocessingRecord;
20 class ASTUnit;
21 
22 namespace cxcursor {
23 
24 class VisitorJob {
25 public:
26   enum Kind {
27     DeclVisitKind,
28     StmtVisitKind,
29     MemberExprPartsKind,
30     TypeLocVisitKind,
31     OverloadExprPartsKind,
32     DeclRefExprPartsKind,
33     LabelRefVisitKind,
34     ExplicitTemplateArgsVisitKind,
35     NestedNameSpecifierLocVisitKind,
36     DeclarationNameInfoVisitKind,
37     MemberRefVisitKind,
38     SizeOfPackExprPartsKind,
39     LambdaExprPartsKind,
40     PostChildrenVisitKind
41   };
42 
43 protected:
44   const void *data[3];
45   CXCursor parent;
46   Kind K;
47   VisitorJob(CXCursor C, Kind k, const void *d1, const void *d2 = nullptr,
48              const void *d3 = nullptr)
parent(C)49       : parent(C), K(k) {
50     data[0] = d1;
51     data[1] = d2;
52     data[2] = d3;
53   }
54 
55 public:
getKind()56   Kind getKind() const { return K; }
getParent()57   const CXCursor &getParent() const { return parent; }
58 };
59 
60 typedef SmallVector<VisitorJob, 10> VisitorWorkList;
61 
62 // Cursor visitor.
63 class CursorVisitor : public DeclVisitor<CursorVisitor, bool>,
64                       public TypeLocVisitor<CursorVisitor, bool> {
65 public:
66   /// Callback called after child nodes of a cursor have been visited.
67   /// Return true to break visitation or false to continue.
68   typedef bool (*PostChildrenVisitorTy)(CXCursor cursor,
69                                         CXClientData client_data);
70 
71 private:
72   /// The translation unit we are traversing.
73   CXTranslationUnit TU;
74   ASTUnit *AU;
75 
76   /// The parent cursor whose children we are traversing.
77   CXCursor Parent;
78 
79   /// The declaration that serves at the parent of any statement or
80   /// expression nodes.
81   const Decl *StmtParent;
82 
83   /// The visitor function.
84   CXCursorVisitor Visitor;
85 
86   PostChildrenVisitorTy PostChildrenVisitor;
87 
88   /// The opaque client data, to be passed along to the visitor.
89   CXClientData ClientData;
90 
91   /// Whether we should visit the preprocessing record entries last,
92   /// after visiting other declarations.
93   bool VisitPreprocessorLast;
94 
95   /// Whether we should visit declarations or preprocessing record
96   /// entries that are #included inside the \arg RegionOfInterest.
97   bool VisitIncludedEntities;
98 
99   /// When valid, a source range to which the cursor should restrict
100   /// its search.
101   SourceRange RegionOfInterest;
102 
103   /// Whether we should only visit declarations and not preprocessing
104   /// record entries.
105   bool VisitDeclsOnly;
106 
107   // FIXME: Eventually remove.  This part of a hack to support proper
108   // iteration over all Decls contained lexically within an ObjC container.
109   DeclContext::decl_iterator *DI_current;
110   DeclContext::decl_iterator DE_current;
111   SmallVectorImpl<Decl *>::iterator *FileDI_current;
112   SmallVectorImpl<Decl *>::iterator FileDE_current;
113 
114   // Cache of pre-allocated worklists for data-recursion walk of Stmts.
115   SmallVector<VisitorWorkList *, 5> WorkListFreeList;
116   SmallVector<VisitorWorkList *, 5> WorkListCache;
117 
118   using DeclVisitor<CursorVisitor, bool>::Visit;
119   using TypeLocVisitor<CursorVisitor, bool>::Visit;
120 
121   /// Determine whether this particular source range comes before, comes
122   /// after, or overlaps the region of interest.
123   ///
124   /// \param R a half-open source range retrieved from the abstract syntax tree.
125   RangeComparisonResult CompareRegionOfInterest(SourceRange R);
126 
127   bool visitDeclsFromFileRegion(FileID File, unsigned Offset, unsigned Length);
128 
129   class SetParentRAII {
130     CXCursor &Parent;
131     const Decl *&StmtParent;
132     CXCursor OldParent;
133 
134   public:
SetParentRAII(CXCursor & Parent,const Decl * & StmtParent,CXCursor NewParent)135     SetParentRAII(CXCursor &Parent, const Decl *&StmtParent, CXCursor NewParent)
136         : Parent(Parent), StmtParent(StmtParent), OldParent(Parent) {
137       Parent = NewParent;
138       if (clang_isDeclaration(Parent.kind))
139         StmtParent = getCursorDecl(Parent);
140     }
141 
~SetParentRAII()142     ~SetParentRAII() {
143       Parent = OldParent;
144       if (clang_isDeclaration(Parent.kind))
145         StmtParent = getCursorDecl(Parent);
146     }
147   };
148 
149 public:
150   CursorVisitor(CXTranslationUnit TU, CXCursorVisitor Visitor,
151                 CXClientData ClientData, bool VisitPreprocessorLast,
152                 bool VisitIncludedPreprocessingEntries = false,
153                 SourceRange RegionOfInterest = SourceRange(),
154                 bool VisitDeclsOnly = false,
155                 PostChildrenVisitorTy PostChildrenVisitor = nullptr)
TU(TU)156       : TU(TU), AU(cxtu::getASTUnit(TU)), Visitor(Visitor),
157         PostChildrenVisitor(PostChildrenVisitor), ClientData(ClientData),
158         VisitPreprocessorLast(VisitPreprocessorLast),
159         VisitIncludedEntities(VisitIncludedPreprocessingEntries),
160         RegionOfInterest(RegionOfInterest), VisitDeclsOnly(VisitDeclsOnly),
161         DI_current(nullptr), FileDI_current(nullptr) {
162     Parent.kind = CXCursor_NoDeclFound;
163     Parent.data[0] = nullptr;
164     Parent.data[1] = nullptr;
165     Parent.data[2] = nullptr;
166     StmtParent = nullptr;
167   }
168 
~CursorVisitor()169   ~CursorVisitor() {
170     // Free the pre-allocated worklists for data-recursion.
171     for (SmallVectorImpl<VisitorWorkList *>::iterator I = WorkListCache.begin(),
172                                                       E = WorkListCache.end();
173          I != E; ++I) {
174       delete *I;
175     }
176   }
177 
getASTUnit()178   ASTUnit *getASTUnit() const { return AU; }
getTU()179   CXTranslationUnit getTU() const { return TU; }
180 
181   bool Visit(CXCursor Cursor, bool CheckedRegionOfInterest = false);
182 
183   /// Visit declarations and preprocessed entities for the file region
184   /// designated by \see RegionOfInterest.
185   bool visitFileRegion();
186 
187   bool visitPreprocessedEntitiesInRegion();
188 
shouldVisitIncludedEntities()189   bool shouldVisitIncludedEntities() const { return VisitIncludedEntities; }
190 
191   template <typename InputIterator>
192   bool visitPreprocessedEntities(InputIterator First, InputIterator Last,
193                                  PreprocessingRecord &PPRec,
194                                  FileID FID = FileID());
195 
196   bool VisitChildren(CXCursor Parent);
197 
198   // Declaration visitors
199   bool VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D);
200   bool VisitTypeAliasDecl(TypeAliasDecl *D);
201   bool VisitAttributes(Decl *D);
202   bool VisitBlockDecl(BlockDecl *B);
203   bool VisitCXXRecordDecl(CXXRecordDecl *D);
204   Optional<bool> shouldVisitCursor(CXCursor C);
205   bool VisitDeclContext(DeclContext *DC);
206   bool VisitTranslationUnitDecl(TranslationUnitDecl *D);
207   bool VisitTypedefDecl(TypedefDecl *D);
208   bool VisitTagDecl(TagDecl *D);
209   bool VisitClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl *D);
210   bool VisitClassTemplatePartialSpecializationDecl(
211       ClassTemplatePartialSpecializationDecl *D);
212   bool VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
213   bool VisitEnumConstantDecl(EnumConstantDecl *D);
214   bool VisitDeclaratorDecl(DeclaratorDecl *DD);
215   bool VisitFunctionDecl(FunctionDecl *ND);
216   bool VisitFieldDecl(FieldDecl *D);
217   bool VisitVarDecl(VarDecl *);
218   bool VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
219   bool VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
220   bool VisitClassTemplateDecl(ClassTemplateDecl *D);
221   bool VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
222   bool VisitObjCTypeParamDecl(ObjCTypeParamDecl *D);
223   bool VisitObjCMethodDecl(ObjCMethodDecl *ND);
224   bool VisitObjCContainerDecl(ObjCContainerDecl *D);
225   bool VisitObjCCategoryDecl(ObjCCategoryDecl *ND);
226   bool VisitObjCProtocolDecl(ObjCProtocolDecl *PID);
227   bool VisitObjCPropertyDecl(ObjCPropertyDecl *PD);
228   bool VisitObjCTypeParamList(ObjCTypeParamList *typeParamList);
229   bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
230   bool VisitObjCImplDecl(ObjCImplDecl *D);
231   bool VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
232   bool VisitObjCImplementationDecl(ObjCImplementationDecl *D);
233   // FIXME: ObjCCompatibleAliasDecl requires aliased-class locations.
234   bool VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PD);
235   bool VisitLinkageSpecDecl(LinkageSpecDecl *D);
236   bool VisitNamespaceDecl(NamespaceDecl *D);
237   bool VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
238   bool VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
239   bool VisitUsingDecl(UsingDecl *D);
240   bool VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
241   bool VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
242   bool VisitStaticAssertDecl(StaticAssertDecl *D);
243   bool VisitFriendDecl(FriendDecl *D);
244   bool VisitDecompositionDecl(DecompositionDecl *D);
245 
246   // Name visitor
247   bool VisitDeclarationNameInfo(DeclarationNameInfo Name);
248   bool VisitNestedNameSpecifier(NestedNameSpecifier *NNS, SourceRange Range);
249   bool VisitNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS);
250 
251   // Template visitors
252   bool VisitTemplateParameters(const TemplateParameterList *Params);
253   bool VisitTemplateName(TemplateName Name, SourceLocation Loc);
254   bool VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL);
255 
256   // Type visitors
257 #define ABSTRACT_TYPELOC(CLASS, PARENT)
258 #define TYPELOC(CLASS, PARENT) bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc);
259 #include "clang/AST/TypeLocNodes.def"
260 
261   bool VisitTagTypeLoc(TagTypeLoc TL);
262   bool VisitArrayTypeLoc(ArrayTypeLoc TL);
263   bool VisitFunctionTypeLoc(FunctionTypeLoc TL, bool SkipResultType = false);
264 
265   // Data-recursive visitor functions.
266   bool IsInRegionOfInterest(CXCursor C);
267   bool RunVisitorWorkList(VisitorWorkList &WL);
268   void EnqueueWorkList(VisitorWorkList &WL, const Stmt *S);
269   LLVM_ATTRIBUTE_NOINLINE bool Visit(const Stmt *S);
270 
271 private:
272   Optional<bool> handleDeclForVisitation(const Decl *D);
273 };
274 
275 } // namespace cxcursor
276 } // namespace clang
277 
278 #endif
279