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