Home | History | Annotate | Download | only in libclang
      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)
     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 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:
    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 
    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)
    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 
    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 
    175   ASTUnit *getASTUnit() const { return static_cast<ASTUnit*>(TU->TUData); }
    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 
    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