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