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