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