Home | History | Annotate | Line # | Download | only in libclang
      1 //===- CXIndexDataConsumer.h - Index data consumer for libclang--*- 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_CXINDEXDATACONSUMER_H
     10 #define LLVM_CLANG_TOOLS_LIBCLANG_CXINDEXDATACONSUMER_H
     11 
     12 #include "CXCursor.h"
     13 #include "Index_Internal.h"
     14 #include "clang/Index/IndexDataConsumer.h"
     15 #include "clang/AST/DeclGroup.h"
     16 #include "clang/AST/DeclObjC.h"
     17 #include "llvm/ADT/DenseSet.h"
     18 
     19 namespace clang {
     20   class FileEntry;
     21   class MSPropertyDecl;
     22   class ObjCPropertyDecl;
     23   class ClassTemplateDecl;
     24   class FunctionTemplateDecl;
     25   class TypeAliasTemplateDecl;
     26   class ClassTemplateSpecializationDecl;
     27 
     28 namespace cxindex {
     29   class CXIndexDataConsumer;
     30   class AttrListInfo;
     31 
     32 class ScratchAlloc {
     33   CXIndexDataConsumer &IdxCtx;
     34 
     35 public:
     36   explicit ScratchAlloc(CXIndexDataConsumer &indexCtx);
     37   ScratchAlloc(const ScratchAlloc &SA);
     38 
     39   ~ScratchAlloc();
     40 
     41   const char *toCStr(StringRef Str);
     42   const char *copyCStr(StringRef Str);
     43 
     44   template <typename T>
     45   T *allocate();
     46 };
     47 
     48 struct EntityInfo : public CXIdxEntityInfo {
     49   const NamedDecl *Dcl;
     50   CXIndexDataConsumer *IndexCtx;
     51   IntrusiveRefCntPtr<AttrListInfo> AttrList;
     52 
     53   EntityInfo() {
     54     name = USR = nullptr;
     55     attributes = nullptr;
     56     numAttributes = 0;
     57   }
     58 };
     59 
     60 struct ContainerInfo : public CXIdxContainerInfo {
     61   const DeclContext *DC;
     62   CXIndexDataConsumer *IndexCtx;
     63 };
     64 
     65 struct DeclInfo : public CXIdxDeclInfo {
     66   enum DInfoKind {
     67     Info_Decl,
     68 
     69     Info_ObjCContainer,
     70       Info_ObjCInterface,
     71       Info_ObjCProtocol,
     72       Info_ObjCCategory,
     73 
     74     Info_ObjCProperty,
     75 
     76     Info_CXXClass
     77   };
     78 
     79   DInfoKind Kind;
     80 
     81   EntityInfo EntInfo;
     82   ContainerInfo SemanticContainer;
     83   ContainerInfo LexicalContainer;
     84   ContainerInfo DeclAsContainer;
     85 
     86   DeclInfo(bool isRedeclaration, bool isDefinition, bool isContainer)
     87     : Kind(Info_Decl) {
     88     this->isRedeclaration = isRedeclaration;
     89     this->isDefinition = isDefinition;
     90     this->isContainer = isContainer;
     91     attributes = nullptr;
     92     numAttributes = 0;
     93     declAsContainer = semanticContainer = lexicalContainer = nullptr;
     94     flags = 0;
     95   }
     96   DeclInfo(DInfoKind K,
     97            bool isRedeclaration, bool isDefinition, bool isContainer)
     98     : Kind(K) {
     99     this->isRedeclaration = isRedeclaration;
    100     this->isDefinition = isDefinition;
    101     this->isContainer = isContainer;
    102     attributes = nullptr;
    103     numAttributes = 0;
    104     declAsContainer = semanticContainer = lexicalContainer = nullptr;
    105     flags = 0;
    106   }
    107 };
    108 
    109 struct ObjCContainerDeclInfo : public DeclInfo {
    110   CXIdxObjCContainerDeclInfo ObjCContDeclInfo;
    111 
    112   ObjCContainerDeclInfo(bool isForwardRef,
    113                         bool isRedeclaration,
    114                         bool isImplementation)
    115     : DeclInfo(Info_ObjCContainer, isRedeclaration,
    116                /*isDefinition=*/!isForwardRef, /*isContainer=*/!isForwardRef) {
    117     init(isForwardRef, isImplementation);
    118   }
    119   ObjCContainerDeclInfo(DInfoKind K,
    120                         bool isForwardRef,
    121                         bool isRedeclaration,
    122                         bool isImplementation)
    123     : DeclInfo(K, isRedeclaration, /*isDefinition=*/!isForwardRef,
    124                /*isContainer=*/!isForwardRef) {
    125     init(isForwardRef, isImplementation);
    126   }
    127 
    128   static bool classof(const DeclInfo *D) {
    129     return Info_ObjCContainer <= D->Kind && D->Kind <= Info_ObjCCategory;
    130   }
    131 
    132 private:
    133   void init(bool isForwardRef, bool isImplementation) {
    134     if (isForwardRef)
    135       ObjCContDeclInfo.kind = CXIdxObjCContainer_ForwardRef;
    136     else if (isImplementation)
    137       ObjCContDeclInfo.kind = CXIdxObjCContainer_Implementation;
    138     else
    139       ObjCContDeclInfo.kind = CXIdxObjCContainer_Interface;
    140   }
    141 };
    142 
    143 struct ObjCInterfaceDeclInfo : public ObjCContainerDeclInfo {
    144   CXIdxObjCInterfaceDeclInfo ObjCInterDeclInfo;
    145   CXIdxObjCProtocolRefListInfo ObjCProtoListInfo;
    146 
    147   ObjCInterfaceDeclInfo(const ObjCInterfaceDecl *D)
    148     : ObjCContainerDeclInfo(Info_ObjCInterface,
    149                             /*isForwardRef=*/false,
    150                             /*isRedeclaration=*/D->getPreviousDecl() != nullptr,
    151                             /*isImplementation=*/false) { }
    152 
    153   static bool classof(const DeclInfo *D) {
    154     return D->Kind == Info_ObjCInterface;
    155   }
    156 };
    157 
    158 struct ObjCProtocolDeclInfo : public ObjCContainerDeclInfo {
    159   CXIdxObjCProtocolRefListInfo ObjCProtoRefListInfo;
    160 
    161   ObjCProtocolDeclInfo(const ObjCProtocolDecl *D)
    162     : ObjCContainerDeclInfo(Info_ObjCProtocol,
    163                             /*isForwardRef=*/false,
    164                             /*isRedeclaration=*/D->getPreviousDecl(),
    165                             /*isImplementation=*/false) { }
    166 
    167   static bool classof(const DeclInfo *D) {
    168     return D->Kind == Info_ObjCProtocol;
    169   }
    170 };
    171 
    172 struct ObjCCategoryDeclInfo : public ObjCContainerDeclInfo {
    173   CXIdxObjCCategoryDeclInfo ObjCCatDeclInfo;
    174   CXIdxObjCProtocolRefListInfo ObjCProtoListInfo;
    175 
    176   explicit ObjCCategoryDeclInfo(bool isImplementation)
    177     : ObjCContainerDeclInfo(Info_ObjCCategory,
    178                             /*isForwardRef=*/false,
    179                             /*isRedeclaration=*/isImplementation,
    180                             /*isImplementation=*/isImplementation) { }
    181 
    182   static bool classof(const DeclInfo *D) {
    183     return D->Kind == Info_ObjCCategory;
    184   }
    185 };
    186 
    187 struct ObjCPropertyDeclInfo : public DeclInfo {
    188   CXIdxObjCPropertyDeclInfo ObjCPropDeclInfo;
    189 
    190   ObjCPropertyDeclInfo()
    191     : DeclInfo(Info_ObjCProperty,
    192                /*isRedeclaration=*/false, /*isDefinition=*/false,
    193                /*isContainer=*/false) { }
    194 
    195   static bool classof(const DeclInfo *D) {
    196     return D->Kind == Info_ObjCProperty;
    197   }
    198 };
    199 
    200 struct CXXClassDeclInfo : public DeclInfo {
    201   CXIdxCXXClassDeclInfo CXXClassInfo;
    202 
    203   CXXClassDeclInfo(bool isRedeclaration, bool isDefinition)
    204     : DeclInfo(Info_CXXClass, isRedeclaration, isDefinition, isDefinition) { }
    205 
    206   static bool classof(const DeclInfo *D) {
    207     return D->Kind == Info_CXXClass;
    208   }
    209 };
    210 
    211 struct AttrInfo : public CXIdxAttrInfo {
    212   const Attr *A;
    213 
    214   AttrInfo(CXIdxAttrKind Kind, CXCursor C, CXIdxLoc Loc, const Attr *A) {
    215     kind = Kind;
    216     cursor = C;
    217     loc = Loc;
    218     this->A = A;
    219   }
    220 };
    221 
    222 struct IBOutletCollectionInfo : public AttrInfo {
    223   EntityInfo ClassInfo;
    224   CXIdxIBOutletCollectionAttrInfo IBCollInfo;
    225 
    226   IBOutletCollectionInfo(CXCursor C, CXIdxLoc Loc, const Attr *A) :
    227     AttrInfo(CXIdxAttr_IBOutletCollection, C, Loc, A) {
    228     assert(C.kind == CXCursor_IBOutletCollectionAttr);
    229     IBCollInfo.objcClass = nullptr;
    230   }
    231 
    232   IBOutletCollectionInfo(const IBOutletCollectionInfo &other);
    233 
    234   static bool classof(const AttrInfo *A) {
    235     return A->kind == CXIdxAttr_IBOutletCollection;
    236   }
    237 };
    238 
    239 class AttrListInfo {
    240   ScratchAlloc SA;
    241 
    242   SmallVector<AttrInfo, 2> Attrs;
    243   SmallVector<IBOutletCollectionInfo, 2> IBCollAttrs;
    244   SmallVector<CXIdxAttrInfo *, 2> CXAttrs;
    245   unsigned ref_cnt;
    246 
    247   AttrListInfo(const AttrListInfo &) = delete;
    248   void operator=(const AttrListInfo &) = delete;
    249 public:
    250   AttrListInfo(const Decl *D, CXIndexDataConsumer &IdxCtx);
    251 
    252   static IntrusiveRefCntPtr<AttrListInfo> create(const Decl *D,
    253                                                  CXIndexDataConsumer &IdxCtx);
    254 
    255   const CXIdxAttrInfo *const *getAttrs() const {
    256     if (CXAttrs.empty())
    257       return nullptr;
    258     return CXAttrs.data();
    259   }
    260   unsigned getNumAttrs() const { return (unsigned)CXAttrs.size(); }
    261 
    262   /// Retain/Release only useful when we allocate a AttrListInfo from the
    263   /// BumpPtrAllocator, and not from the stack; so that we keep a pointer
    264   // in the EntityInfo
    265   void Retain() { ++ref_cnt; }
    266   void Release() {
    267     assert (ref_cnt > 0 && "Reference count is already zero.");
    268     if (--ref_cnt == 0) {
    269       // Memory is allocated from a BumpPtrAllocator, no need to delete it.
    270       this->~AttrListInfo();
    271     }
    272   }
    273 };
    274 
    275 class CXIndexDataConsumer : public index::IndexDataConsumer {
    276   ASTContext *Ctx;
    277   CXClientData ClientData;
    278   IndexerCallbacks &CB;
    279   unsigned IndexOptions;
    280   CXTranslationUnit CXTU;
    281 
    282   typedef llvm::DenseMap<const FileEntry *, CXIdxClientFile> FileMapTy;
    283   typedef llvm::DenseMap<const DeclContext *, CXIdxClientContainer>
    284     ContainerMapTy;
    285   typedef llvm::DenseMap<const Decl *, CXIdxClientEntity> EntityMapTy;
    286 
    287   FileMapTy FileMap;
    288   ContainerMapTy ContainerMap;
    289   EntityMapTy EntityMap;
    290 
    291   typedef std::pair<const FileEntry *, const Decl *> RefFileOccurrence;
    292   llvm::DenseSet<RefFileOccurrence> RefFileOccurrences;
    293 
    294   llvm::BumpPtrAllocator StrScratch;
    295   unsigned StrAdapterCount;
    296   friend class ScratchAlloc;
    297 
    298   struct ObjCProtocolListInfo {
    299     SmallVector<CXIdxObjCProtocolRefInfo, 4> ProtInfos;
    300     SmallVector<EntityInfo, 4> ProtEntities;
    301     SmallVector<CXIdxObjCProtocolRefInfo *, 4> Prots;
    302 
    303     CXIdxObjCProtocolRefListInfo getListInfo() const {
    304       CXIdxObjCProtocolRefListInfo Info = { Prots.data(),
    305                                             (unsigned)Prots.size() };
    306       return Info;
    307     }
    308 
    309     ObjCProtocolListInfo(const ObjCProtocolList &ProtList,
    310                          CXIndexDataConsumer &IdxCtx,
    311                          ScratchAlloc &SA);
    312   };
    313 
    314   struct CXXBasesListInfo {
    315     SmallVector<CXIdxBaseClassInfo, 4> BaseInfos;
    316     SmallVector<EntityInfo, 4> BaseEntities;
    317     SmallVector<CXIdxBaseClassInfo *, 4> CXBases;
    318 
    319     const CXIdxBaseClassInfo *const *getBases() const {
    320       return CXBases.data();
    321     }
    322     unsigned getNumBases() const { return (unsigned)CXBases.size(); }
    323 
    324     CXXBasesListInfo(const CXXRecordDecl *D,
    325                      CXIndexDataConsumer &IdxCtx, ScratchAlloc &SA);
    326 
    327   private:
    328     SourceLocation getBaseLoc(const CXXBaseSpecifier &Base) const;
    329   };
    330 
    331   friend class AttrListInfo;
    332 
    333 public:
    334   CXIndexDataConsumer(CXClientData clientData, IndexerCallbacks &indexCallbacks,
    335                   unsigned indexOptions, CXTranslationUnit cxTU)
    336     : Ctx(nullptr), ClientData(clientData), CB(indexCallbacks),
    337       IndexOptions(indexOptions), CXTU(cxTU),
    338       StrScratch(), StrAdapterCount(0) { }
    339 
    340   ASTContext &getASTContext() const { return *Ctx; }
    341   CXTranslationUnit getCXTU() const { return CXTU; }
    342 
    343   void setASTContext(ASTContext &ctx);
    344   void setPreprocessor(std::shared_ptr<Preprocessor> PP) override;
    345 
    346   bool shouldSuppressRefs() const {
    347     return IndexOptions & CXIndexOpt_SuppressRedundantRefs;
    348   }
    349 
    350   bool shouldIndexFunctionLocalSymbols() const {
    351     return IndexOptions & CXIndexOpt_IndexFunctionLocalSymbols;
    352   }
    353 
    354   bool shouldIndexImplicitTemplateInsts() const {
    355     return IndexOptions & CXIndexOpt_IndexImplicitTemplateInstantiations;
    356   }
    357 
    358   static bool isFunctionLocalDecl(const Decl *D);
    359 
    360   bool shouldAbort();
    361 
    362   bool hasDiagnosticCallback() const { return CB.diagnostic; }
    363 
    364   void enteredMainFile(const FileEntry *File);
    365 
    366   void ppIncludedFile(SourceLocation hashLoc,
    367                       StringRef filename, const FileEntry *File,
    368                       bool isImport, bool isAngled, bool isModuleImport);
    369 
    370   void importedModule(const ImportDecl *ImportD);
    371   void importedPCH(const FileEntry *File);
    372 
    373   void startedTranslationUnit();
    374 
    375   void indexDiagnostics();
    376 
    377   void handleDiagnosticSet(CXDiagnosticSet CXDiagSet);
    378 
    379   bool handleFunction(const FunctionDecl *FD);
    380 
    381   bool handleVar(const VarDecl *D);
    382 
    383   bool handleField(const FieldDecl *D);
    384 
    385   bool handleEnumerator(const EnumConstantDecl *D);
    386 
    387   bool handleTagDecl(const TagDecl *D);
    388 
    389   bool handleTypedefName(const TypedefNameDecl *D);
    390 
    391   bool handleObjCInterface(const ObjCInterfaceDecl *D);
    392   bool handleObjCImplementation(const ObjCImplementationDecl *D);
    393 
    394   bool handleObjCProtocol(const ObjCProtocolDecl *D);
    395 
    396   bool handleObjCCategory(const ObjCCategoryDecl *D);
    397   bool handleObjCCategoryImpl(const ObjCCategoryImplDecl *D);
    398 
    399   bool handleObjCMethod(const ObjCMethodDecl *D, SourceLocation Loc);
    400 
    401   bool handleSynthesizedObjCProperty(const ObjCPropertyImplDecl *D);
    402   bool handleSynthesizedObjCMethod(const ObjCMethodDecl *D, SourceLocation Loc,
    403                                    const DeclContext *LexicalDC);
    404 
    405   bool handleObjCProperty(const ObjCPropertyDecl *D);
    406 
    407   bool handleNamespace(const NamespaceDecl *D);
    408 
    409   bool handleClassTemplate(const ClassTemplateDecl *D);
    410   bool handleFunctionTemplate(const FunctionTemplateDecl *D);
    411   bool handleTypeAliasTemplate(const TypeAliasTemplateDecl *D);
    412 
    413   bool handleReference(const NamedDecl *D, SourceLocation Loc, CXCursor Cursor,
    414                        const NamedDecl *Parent,
    415                        const DeclContext *DC,
    416                        const Expr *E = nullptr,
    417                        CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct,
    418                        CXSymbolRole Role = CXSymbolRole_None);
    419 
    420   bool isNotFromSourceFile(SourceLocation Loc) const;
    421 
    422   void translateLoc(SourceLocation Loc, CXIdxClientFile *indexFile, CXFile *file,
    423                     unsigned *line, unsigned *column, unsigned *offset);
    424 
    425   CXIdxClientContainer getClientContainerForDC(const DeclContext *DC) const;
    426   void addContainerInMap(const DeclContext *DC, CXIdxClientContainer container);
    427 
    428   CXIdxClientEntity getClientEntity(const Decl *D) const;
    429   void setClientEntity(const Decl *D, CXIdxClientEntity client);
    430 
    431   static bool isTemplateImplicitInstantiation(const Decl *D);
    432 
    433 private:
    434   bool handleDeclOccurrence(const Decl *D, index::SymbolRoleSet Roles,
    435                             ArrayRef<index::SymbolRelation> Relations,
    436                             SourceLocation Loc, ASTNodeInfo ASTNode) override;
    437 
    438   bool handleModuleOccurrence(const ImportDecl *ImportD, const Module *Mod,
    439                               index::SymbolRoleSet Roles,
    440                               SourceLocation Loc) override;
    441 
    442   void finish() override;
    443 
    444   bool handleDecl(const NamedDecl *D,
    445                   SourceLocation Loc, CXCursor Cursor,
    446                   DeclInfo &DInfo,
    447                   const DeclContext *LexicalDC = nullptr,
    448                   const DeclContext *SemaDC = nullptr);
    449 
    450   bool handleObjCContainer(const ObjCContainerDecl *D,
    451                            SourceLocation Loc, CXCursor Cursor,
    452                            ObjCContainerDeclInfo &ContDInfo);
    453 
    454   bool handleCXXRecordDecl(const CXXRecordDecl *RD, const NamedDecl *OrigD);
    455 
    456   bool markEntityOccurrenceInFile(const NamedDecl *D, SourceLocation Loc);
    457 
    458   const NamedDecl *getEntityDecl(const NamedDecl *D) const;
    459 
    460   const DeclContext *getEntityContainer(const Decl *D) const;
    461 
    462   CXIdxClientFile getIndexFile(const FileEntry *File);
    463 
    464   CXIdxLoc getIndexLoc(SourceLocation Loc) const;
    465 
    466   void getEntityInfo(const NamedDecl *D,
    467                      EntityInfo &EntityInfo,
    468                      ScratchAlloc &SA);
    469 
    470   void getContainerInfo(const DeclContext *DC, ContainerInfo &ContInfo);
    471 
    472   CXCursor getCursor(const Decl *D) {
    473     return cxcursor::MakeCXCursor(D, CXTU);
    474   }
    475 
    476   CXCursor getRefCursor(const NamedDecl *D, SourceLocation Loc);
    477 
    478   static bool shouldIgnoreIfImplicit(const Decl *D);
    479 };
    480 
    481 inline ScratchAlloc::ScratchAlloc(CXIndexDataConsumer &idxCtx) : IdxCtx(idxCtx) {
    482   ++IdxCtx.StrAdapterCount;
    483 }
    484 inline ScratchAlloc::ScratchAlloc(const ScratchAlloc &SA) : IdxCtx(SA.IdxCtx) {
    485   ++IdxCtx.StrAdapterCount;
    486 }
    487 
    488 inline ScratchAlloc::~ScratchAlloc() {
    489   --IdxCtx.StrAdapterCount;
    490   if (IdxCtx.StrAdapterCount == 0)
    491     IdxCtx.StrScratch.Reset();
    492 }
    493 
    494 template <typename T>
    495 inline T *ScratchAlloc::allocate() {
    496   return IdxCtx.StrScratch.Allocate<T>();
    497 }
    498 
    499 }} // end clang::cxindex
    500 
    501 #endif
    502