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