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