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