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