| //===- CursorVisitor.h - CursorVisitor interface ----------------*- C++ -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LLVM_CLANG_TOOLS_LIBCLANG_CURSORVISITOR_H |
| #define LLVM_CLANG_TOOLS_LIBCLANG_CURSORVISITOR_H |
| |
| #include "CXCursor.h" |
| #include "CXTranslationUnit.h" |
| #include "Index_Internal.h" |
| #include "clang/AST/DeclVisitor.h" |
| #include "clang/AST/TypeLocVisitor.h" |
| |
| namespace clang { |
| class PreprocessingRecord; |
| class ASTUnit; |
| |
| namespace cxcursor { |
| |
| class VisitorJob { |
| public: |
| enum Kind { |
| DeclVisitKind, |
| StmtVisitKind, |
| MemberExprPartsKind, |
| TypeLocVisitKind, |
| OverloadExprPartsKind, |
| DeclRefExprPartsKind, |
| LabelRefVisitKind, |
| ExplicitTemplateArgsVisitKind, |
| NestedNameSpecifierLocVisitKind, |
| DeclarationNameInfoVisitKind, |
| MemberRefVisitKind, |
| SizeOfPackExprPartsKind, |
| LambdaExprPartsKind, |
| PostChildrenVisitKind |
| }; |
| |
| protected: |
| const void *data[3]; |
| CXCursor parent; |
| Kind K; |
| VisitorJob(CXCursor C, Kind k, const void *d1, const void *d2 = nullptr, |
| const void *d3 = nullptr) |
| : parent(C), K(k) { |
| data[0] = d1; |
| data[1] = d2; |
| data[2] = d3; |
| } |
| |
| public: |
| Kind getKind() const { return K; } |
| const CXCursor &getParent() const { return parent; } |
| }; |
| |
| typedef SmallVector<VisitorJob, 10> VisitorWorkList; |
| |
| // Cursor visitor. |
| class CursorVisitor : public DeclVisitor<CursorVisitor, bool>, |
| public TypeLocVisitor<CursorVisitor, bool> { |
| public: |
| /// Callback called after child nodes of a cursor have been visited. |
| /// Return true to break visitation or false to continue. |
| typedef bool (*PostChildrenVisitorTy)(CXCursor cursor, |
| CXClientData client_data); |
| |
| private: |
| /// The translation unit we are traversing. |
| CXTranslationUnit TU; |
| ASTUnit *AU; |
| |
| /// The parent cursor whose children we are traversing. |
| CXCursor Parent; |
| |
| /// The declaration that serves at the parent of any statement or |
| /// expression nodes. |
| const Decl *StmtParent; |
| |
| /// The visitor function. |
| CXCursorVisitor Visitor; |
| |
| PostChildrenVisitorTy PostChildrenVisitor; |
| |
| /// The opaque client data, to be passed along to the visitor. |
| CXClientData ClientData; |
| |
| /// Whether we should visit the preprocessing record entries last, |
| /// after visiting other declarations. |
| bool VisitPreprocessorLast; |
| |
| /// Whether we should visit declarations or preprocessing record |
| /// entries that are #included inside the \arg RegionOfInterest. |
| bool VisitIncludedEntities; |
| |
| /// When valid, a source range to which the cursor should restrict |
| /// its search. |
| SourceRange RegionOfInterest; |
| |
| /// Whether we should only visit declarations and not preprocessing |
| /// record entries. |
| bool VisitDeclsOnly; |
| |
| // FIXME: Eventually remove. This part of a hack to support proper |
| // iteration over all Decls contained lexically within an ObjC container. |
| DeclContext::decl_iterator *DI_current; |
| DeclContext::decl_iterator DE_current; |
| SmallVectorImpl<Decl *>::iterator *FileDI_current; |
| SmallVectorImpl<Decl *>::iterator FileDE_current; |
| |
| // Cache of pre-allocated worklists for data-recursion walk of Stmts. |
| SmallVector<VisitorWorkList *, 5> WorkListFreeList; |
| SmallVector<VisitorWorkList *, 5> WorkListCache; |
| |
| using DeclVisitor<CursorVisitor, bool>::Visit; |
| using TypeLocVisitor<CursorVisitor, bool>::Visit; |
| |
| /// Determine whether this particular source range comes before, comes |
| /// after, or overlaps the region of interest. |
| /// |
| /// \param R a half-open source range retrieved from the abstract syntax tree. |
| RangeComparisonResult CompareRegionOfInterest(SourceRange R); |
| |
| bool visitDeclsFromFileRegion(FileID File, unsigned Offset, unsigned Length); |
| |
| class SetParentRAII { |
| CXCursor &Parent; |
| const Decl *&StmtParent; |
| CXCursor OldParent; |
| |
| public: |
| SetParentRAII(CXCursor &Parent, const Decl *&StmtParent, CXCursor NewParent) |
| : Parent(Parent), StmtParent(StmtParent), OldParent(Parent) { |
| Parent = NewParent; |
| if (clang_isDeclaration(Parent.kind)) |
| StmtParent = getCursorDecl(Parent); |
| } |
| |
| ~SetParentRAII() { |
| Parent = OldParent; |
| if (clang_isDeclaration(Parent.kind)) |
| StmtParent = getCursorDecl(Parent); |
| } |
| }; |
| |
| public: |
| CursorVisitor(CXTranslationUnit TU, CXCursorVisitor Visitor, |
| CXClientData ClientData, bool VisitPreprocessorLast, |
| bool VisitIncludedPreprocessingEntries = false, |
| SourceRange RegionOfInterest = SourceRange(), |
| bool VisitDeclsOnly = false, |
| PostChildrenVisitorTy PostChildrenVisitor = nullptr) |
| : TU(TU), AU(cxtu::getASTUnit(TU)), Visitor(Visitor), |
| PostChildrenVisitor(PostChildrenVisitor), ClientData(ClientData), |
| VisitPreprocessorLast(VisitPreprocessorLast), |
| VisitIncludedEntities(VisitIncludedPreprocessingEntries), |
| RegionOfInterest(RegionOfInterest), VisitDeclsOnly(VisitDeclsOnly), |
| DI_current(nullptr), FileDI_current(nullptr) { |
| Parent.kind = CXCursor_NoDeclFound; |
| Parent.data[0] = nullptr; |
| Parent.data[1] = nullptr; |
| Parent.data[2] = nullptr; |
| StmtParent = nullptr; |
| } |
| |
| ~CursorVisitor() { |
| // Free the pre-allocated worklists for data-recursion. |
| for (SmallVectorImpl<VisitorWorkList *>::iterator I = WorkListCache.begin(), |
| E = WorkListCache.end(); |
| I != E; ++I) { |
| delete *I; |
| } |
| } |
| |
| ASTUnit *getASTUnit() const { return AU; } |
| CXTranslationUnit getTU() const { return TU; } |
| |
| bool Visit(CXCursor Cursor, bool CheckedRegionOfInterest = false); |
| |
| /// Visit declarations and preprocessed entities for the file region |
| /// designated by \see RegionOfInterest. |
| bool visitFileRegion(); |
| |
| bool visitPreprocessedEntitiesInRegion(); |
| |
| bool shouldVisitIncludedEntities() const { return VisitIncludedEntities; } |
| |
| template <typename InputIterator> |
| bool visitPreprocessedEntities(InputIterator First, InputIterator Last, |
| PreprocessingRecord &PPRec, |
| FileID FID = FileID()); |
| |
| bool VisitChildren(CXCursor Parent); |
| |
| // Declaration visitors |
| bool VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D); |
| bool VisitTypeAliasDecl(TypeAliasDecl *D); |
| bool VisitAttributes(Decl *D); |
| bool VisitBlockDecl(BlockDecl *B); |
| bool VisitCXXRecordDecl(CXXRecordDecl *D); |
| Optional<bool> shouldVisitCursor(CXCursor C); |
| bool VisitDeclContext(DeclContext *DC); |
| bool VisitTranslationUnitDecl(TranslationUnitDecl *D); |
| bool VisitTypedefDecl(TypedefDecl *D); |
| bool VisitTagDecl(TagDecl *D); |
| bool VisitClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl *D); |
| bool VisitClassTemplatePartialSpecializationDecl( |
| ClassTemplatePartialSpecializationDecl *D); |
| bool VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D); |
| bool VisitEnumConstantDecl(EnumConstantDecl *D); |
| bool VisitDeclaratorDecl(DeclaratorDecl *DD); |
| bool VisitFunctionDecl(FunctionDecl *ND); |
| bool VisitFieldDecl(FieldDecl *D); |
| bool VisitVarDecl(VarDecl *); |
| bool VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D); |
| bool VisitFunctionTemplateDecl(FunctionTemplateDecl *D); |
| bool VisitClassTemplateDecl(ClassTemplateDecl *D); |
| bool VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D); |
| bool VisitObjCTypeParamDecl(ObjCTypeParamDecl *D); |
| bool VisitObjCMethodDecl(ObjCMethodDecl *ND); |
| bool VisitObjCContainerDecl(ObjCContainerDecl *D); |
| bool VisitObjCCategoryDecl(ObjCCategoryDecl *ND); |
| bool VisitObjCProtocolDecl(ObjCProtocolDecl *PID); |
| bool VisitObjCPropertyDecl(ObjCPropertyDecl *PD); |
| bool VisitObjCTypeParamList(ObjCTypeParamList *typeParamList); |
| bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *D); |
| bool VisitObjCImplDecl(ObjCImplDecl *D); |
| bool VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D); |
| bool VisitObjCImplementationDecl(ObjCImplementationDecl *D); |
| // FIXME: ObjCCompatibleAliasDecl requires aliased-class locations. |
| bool VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PD); |
| bool VisitLinkageSpecDecl(LinkageSpecDecl *D); |
| bool VisitNamespaceDecl(NamespaceDecl *D); |
| bool VisitNamespaceAliasDecl(NamespaceAliasDecl *D); |
| bool VisitUsingDirectiveDecl(UsingDirectiveDecl *D); |
| bool VisitUsingDecl(UsingDecl *D); |
| bool VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D); |
| bool VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D); |
| bool VisitStaticAssertDecl(StaticAssertDecl *D); |
| bool VisitFriendDecl(FriendDecl *D); |
| bool VisitDecompositionDecl(DecompositionDecl *D); |
| |
| // Name visitor |
| bool VisitDeclarationNameInfo(DeclarationNameInfo Name); |
| bool VisitNestedNameSpecifier(NestedNameSpecifier *NNS, SourceRange Range); |
| bool VisitNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS); |
| |
| // Template visitors |
| bool VisitTemplateParameters(const TemplateParameterList *Params); |
| bool VisitTemplateName(TemplateName Name, SourceLocation Loc); |
| bool VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL); |
| |
| // Type visitors |
| #define ABSTRACT_TYPELOC(CLASS, PARENT) |
| #define TYPELOC(CLASS, PARENT) bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc); |
| #include "clang/AST/TypeLocNodes.def" |
| |
| bool VisitTagTypeLoc(TagTypeLoc TL); |
| bool VisitArrayTypeLoc(ArrayTypeLoc TL); |
| bool VisitFunctionTypeLoc(FunctionTypeLoc TL, bool SkipResultType = false); |
| |
| // Data-recursive visitor functions. |
| bool IsInRegionOfInterest(CXCursor C); |
| bool RunVisitorWorkList(VisitorWorkList &WL); |
| void EnqueueWorkList(VisitorWorkList &WL, const Stmt *S); |
| LLVM_ATTRIBUTE_NOINLINE bool Visit(const Stmt *S); |
| |
| private: |
| Optional<bool> handleDeclForVisitation(const Decl *D); |
| }; |
| |
| } // namespace cxcursor |
| } // namespace clang |
| |
| #endif |