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