Home | History | Annotate | Line # | Download | only in libclang
      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