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