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