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