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