291 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLVM_CLANG_TOOLS_LIBCLANG_CURSORVISITOR_H10#define LLVM_CLANG_TOOLS_LIBCLANG_CURSORVISITOR_H11 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 19namespace clang {20class PreprocessingRecord;21class ASTUnit;22 23namespace concepts {24class Requirement;25}26 27namespace cxcursor {28 29class VisitorJob {30public: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 PostChildrenVisitKind48 };49 50protected: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)56 : parent(C), K(k) {57 data[0] = d1;58 data[1] = d2;59 data[2] = d3;60 }61 62public:63 Kind getKind() const { return K; }64 const CXCursor &getParent() const { return parent; }65};66 67typedef SmallVector<VisitorJob, 10> VisitorWorkList;68 69// Cursor visitor.70class CursorVisitor : public DeclVisitor<CursorVisitor, bool>,71 public TypeLocVisitor<CursorVisitor, bool> {72public: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 78private: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 or87 /// 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 record103 /// entries that are #included inside the \arg RegionOfInterest.104 bool VisitIncludedEntities;105 106 /// When valid, a source range to which the cursor should restrict107 /// its search.108 SourceRange RegionOfInterest;109 110 /// Whether we should only visit declarations and not preprocessing111 /// record entries.112 bool VisitDeclsOnly;113 114 // FIXME: Eventually remove. This part of a hack to support proper115 // 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, comes129 /// 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: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 149 ~SetParentRAII() {150 Parent = OldParent;151 if (clang_isDeclaration(Parent.kind))152 StmtParent = getCursorDecl(Parent);153 }154 };155 156public: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)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 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 185 ASTUnit *getASTUnit() const { return AU; }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 region191 /// designated by \see RegionOfInterest.192 bool visitFileRegion();193 194 bool visitPreprocessedEntitiesInRegion();195 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 visitors206 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 visitor257 bool VisitDeclarationNameInfo(DeclarationNameInfo Name);258 bool VisitNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS);259 260 // Template visitors261 bool VisitTemplateParameters(const TemplateParameterList *Params);262 bool VisitTemplateName(TemplateName Name, SourceLocation NameLoc,263 NestedNameSpecifierLoc NNS);264 bool VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL);265 266 // Type visitors267#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 void EnqueueWorkList(VisitorWorkList &WL, const Attr *A);280 LLVM_ATTRIBUTE_NOINLINE bool Visit(const Stmt *S);281 LLVM_ATTRIBUTE_NOINLINE bool Visit(const Attr *A);282 283private:284 std::optional<bool> handleDeclForVisitation(const Decl *D);285};286 287} // namespace cxcursor288} // namespace clang289 290#endif291