From 643d3ce93c501d19353f2fa578fee3e97f1d1b4b Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis <akyrtzi@gmail.com> Date: Thu, 15 Dec 2011 00:05:00 +0000 Subject: [PATCH] [libclang] Indexing API: provide an attribute list inside CXIdxEntityInfo so that we can access the attributes of an entity for a reference. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@146616 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang-c/Index.h | 28 ++++---- tools/c-index-test/c-index-test.c | 7 ++ tools/libclang/IndexingContext.cpp | 73 +++++++++++++++----- tools/libclang/IndexingContext.h | 105 +++++++++++++++++++---------- 4 files changed, 148 insertions(+), 65 deletions(-) diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index 9da6b2370f7..d9d027e2a6e 100644 --- a/include/clang-c/Index.h +++ b/include/clang-c/Index.h @@ -4171,19 +4171,6 @@ typedef enum { CXIdxEntity_TemplateSpecialization = 3 } CXIdxEntityCXXTemplateKind; -typedef struct { - CXIdxEntityKind kind; - CXIdxEntityCXXTemplateKind templateKind; - CXIdxEntityLanguage lang; - const char *name; - const char *USR; - CXCursor cursor; -} CXIdxEntityInfo; - -typedef struct { - CXCursor cursor; -} CXIdxContainerInfo; - typedef enum { CXIdxAttr_Unexposed = 0, CXIdxAttr_IBAction = 1, @@ -4197,6 +4184,21 @@ typedef struct { CXIdxLoc loc; } CXIdxAttrInfo; +typedef struct { + CXIdxEntityKind kind; + CXIdxEntityCXXTemplateKind templateKind; + CXIdxEntityLanguage lang; + const char *name; + const char *USR; + CXCursor cursor; + const CXIdxAttrInfo *const *attributes; + unsigned numAttributes; +} CXIdxEntityInfo; + +typedef struct { + CXCursor cursor; +} CXIdxContainerInfo; + typedef struct { const CXIdxAttrInfo *attrInfo; const CXIdxEntityInfo *objcClass; diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c index fdc88a015ea..d46f2dc4998 100644 --- a/tools/c-index-test/c-index-test.c +++ b/tools/c-index-test/c-index-test.c @@ -1684,6 +1684,7 @@ static void printEntityInfo(const char *cb, const CXIdxEntityInfo *info) { const char *name; IndexData *index_data; + unsigned i; index_data = (IndexData *)client_data; printCheck(index_data); @@ -1701,6 +1702,12 @@ static void printEntityInfo(const char *cb, printf(" | name: %s", name); printf(" | USR: %s", info->USR); printf(" | lang: %s", getEntityLanguageString(info->lang)); + + for (i = 0; i != info->numAttributes; ++i) { + const CXIdxAttrInfo *Attr = info->attributes[i]; + printf(" <attribute>: "); + PrintCursor(Attr->cursor); + } } static void printBaseClassInfo(CXClientData client_data, diff --git a/tools/libclang/IndexingContext.cpp b/tools/libclang/IndexingContext.cpp index 8d27d85a55d..23d8e7e5696 100644 --- a/tools/libclang/IndexingContext.cpp +++ b/tools/libclang/IndexingContext.cpp @@ -22,7 +22,7 @@ using namespace cxcursor; IndexingContext::ObjCProtocolListInfo::ObjCProtocolListInfo( const ObjCProtocolList &ProtList, IndexingContext &IdxCtx, - StrAdapter &SA) { + ScratchAlloc &SA) { ObjCInterfaceDecl::protocol_loc_iterator LI = ProtList.loc_begin(); for (ObjCInterfaceDecl::protocol_iterator I = ProtList.begin(), E = ProtList.end(); I != E; ++I, ++LI) { @@ -46,9 +46,27 @@ IndexingContext::ObjCProtocolListInfo::ObjCProtocolListInfo( Prots.push_back(&ProtInfos[i]); } -IndexingContext::AttrListInfo::AttrListInfo(const Decl *D, - IndexingContext &IdxCtx, - StrAdapter &SA) { + +IBOutletCollectionInfo::IBOutletCollectionInfo( + const IBOutletCollectionInfo &other) + : AttrInfo(CXIdxAttr_IBOutletCollection, other.cursor, other.loc, A) { + + IBCollInfo.attrInfo = this; + IBCollInfo.classCursor = other.IBCollInfo.classCursor; + IBCollInfo.classLoc = other.IBCollInfo.classLoc; + if (other.IBCollInfo.objcClass) { + ClassInfo = other.ClassInfo; + IBCollInfo.objcClass = &ClassInfo; + } else + IBCollInfo.objcClass = 0; +} + +AttrListInfo::AttrListInfo(const Decl *D, + IndexingContext &IdxCtx, + ScratchAlloc &SA) : ref_cnt(0) { + if (!D->hasAttrs()) + return; + for (AttrVec::const_iterator AttrI = D->attr_begin(), AttrE = D->attr_end(); AttrI != AttrE; ++AttrI) { const Attr *A = *AttrI; @@ -95,9 +113,24 @@ IndexingContext::AttrListInfo::AttrListInfo(const Decl *D, CXAttrs.push_back(&Attrs[i]); } +AttrListInfo::AttrListInfo(const AttrListInfo &other) { + assert(other.ref_cnt == 0 && + "Should not copy an AttrListInfo that is ref-counted"); + ref_cnt = 0; + + Attrs = other.Attrs; + IBCollAttrs = other.IBCollAttrs; + + for (unsigned i = 0, e = IBCollAttrs.size(); i != e; ++i) + CXAttrs.push_back(&IBCollAttrs[i]); + + for (unsigned i = 0, e = Attrs.size(); i != e; ++i) + CXAttrs.push_back(&Attrs[i]); +} + IndexingContext::CXXBasesListInfo::CXXBasesListInfo(const CXXRecordDecl *D, IndexingContext &IdxCtx, - IndexingContext::StrAdapter &SA) { + ScratchAlloc &SA) { for (CXXRecordDecl::base_class_const_iterator I = D->bases_begin(), E = D->bases_end(); I != E; ++I) { const CXXBaseSpecifier &Base = *I; @@ -155,7 +188,7 @@ SourceLocation IndexingContext::CXXBasesListInfo::getBaseLoc( return Loc; } -const char *IndexingContext::StrAdapter::toCStr(StringRef Str) { +const char *ScratchAlloc::toCStr(StringRef Str) { if (Str.empty()) return ""; if (Str.data()[Str.size()] == '\0') @@ -163,7 +196,7 @@ const char *IndexingContext::StrAdapter::toCStr(StringRef Str) { return copyCStr(Str); } -const char *IndexingContext::StrAdapter::copyCStr(StringRef Str) { +const char *ScratchAlloc::copyCStr(StringRef Str) { char *buf = IdxCtx.StrScratch.Allocate<char>(Str.size() + 1); std::uninitialized_copy(Str.begin(), Str.end(), buf); buf[Str.size()] = '\0'; @@ -195,7 +228,7 @@ void IndexingContext::ppIncludedFile(SourceLocation hashLoc, if (!CB.ppIncludedFile) return; - StrAdapter SA(*this); + ScratchAlloc SA(*this); CXIdxIncludedFileInfo Info = { getIndexLoc(hashLoc), SA.toCStr(filename), (CXFile)File, @@ -226,7 +259,7 @@ bool IndexingContext::handleDecl(const NamedDecl *D, if (D->isImplicit() && shouldIgnoreIfImplicit(D)) return false; - StrAdapter SA(*this); + ScratchAlloc SA(*this); getEntityInfo(D, DInfo.EntInfo, SA); if (!DInfo.EntInfo.USR || Loc.isInvalid()) return false; @@ -320,7 +353,7 @@ bool IndexingContext::handleObjCClass(const ObjCClassDecl *D) { } bool IndexingContext::handleObjCInterface(const ObjCInterfaceDecl *D) { - StrAdapter SA(*this); + ScratchAlloc SA(*this); CXIdxBaseClassInfo BaseClass; EntityInfo BaseEntity; @@ -366,7 +399,7 @@ bool IndexingContext::handleObjCForwardProtocol(const ObjCProtocolDecl *D, } bool IndexingContext::handleObjCProtocol(const ObjCProtocolDecl *D) { - StrAdapter SA(*this); + ScratchAlloc SA(*this); ObjCProtocolListInfo ProtListInfo(D->getReferencedProtocols(), *this, SA); ObjCProtocolDeclInfo ProtInfo(D); @@ -378,7 +411,7 @@ bool IndexingContext::handleObjCProtocol(const ObjCProtocolDecl *D) { bool IndexingContext::handleObjCCategory(const ObjCCategoryDecl *D) { ObjCCategoryDeclInfo CatDInfo(/*isImplementation=*/false); EntityInfo ClassEntity; - StrAdapter SA(*this); + ScratchAlloc SA(*this); const ObjCInterfaceDecl *IFaceD = D->getClassInterface(); SourceLocation ClassLoc = D->getLocation(); SourceLocation CategoryLoc = D->IsClassExtension() ? ClassLoc @@ -410,7 +443,7 @@ bool IndexingContext::handleObjCCategoryImpl(const ObjCCategoryImplDecl *D) { const ObjCCategoryDecl *CatD = D->getCategoryDecl(); ObjCCategoryDeclInfo CatDInfo(/*isImplementation=*/true); EntityInfo ClassEntity; - StrAdapter SA(*this); + ScratchAlloc SA(*this); const ObjCInterfaceDecl *IFaceD = CatD->getClassInterface(); SourceLocation ClassLoc = D->getLocation(); SourceLocation CategoryLoc = D->getCategoryNameLoc(); @@ -519,7 +552,7 @@ bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc, return false; // already occurred. } - StrAdapter SA(*this); + ScratchAlloc SA(*this); EntityInfo RefEntity, ParentEntity; getEntityInfo(D, RefEntity, SA); if (!RefEntity.USR) @@ -586,7 +619,7 @@ void IndexingContext::setClientEntity(const Decl *D, CXIdxClientEntity client) { bool IndexingContext::handleCXXRecordDecl(const CXXRecordDecl *RD, const NamedDecl *OrigD) { if (RD->isThisDeclarationADefinition()) { - StrAdapter SA(*this); + ScratchAlloc SA(*this); CXXClassDeclInfo CXXDInfo(/*isRedeclaration=*/!OrigD->isCanonicalDecl(), /*isDefinition=*/RD->isThisDeclarationADefinition()); CXXBasesListInfo BaseList(RD, *this, SA); @@ -731,7 +764,7 @@ void IndexingContext::translateLoc(SourceLocation Loc, void IndexingContext::getEntityInfo(const NamedDecl *D, EntityInfo &EntityInfo, - StrAdapter &SA) { + ScratchAlloc &SA) { if (!D) return; @@ -743,6 +776,14 @@ void IndexingContext::getEntityInfo(const NamedDecl *D, EntityInfo.templateKind = CXIdxEntity_NonTemplate; EntityInfo.lang = CXIdxEntityLang_C; + if (D->hasAttrs()) { + AttrListInfo *attrs = SA.allocate<AttrListInfo>(); + new (attrs) AttrListInfo(D, *this, SA); + EntityInfo.AttrList = attrs; + EntityInfo.attributes = attrs->getAttrs(); + EntityInfo.numAttributes = attrs->getNumAttrs(); + } + if (const TagDecl *TD = dyn_cast<TagDecl>(D)) { switch (TD->getTagKind()) { case TTK_Struct: diff --git a/tools/libclang/IndexingContext.h b/tools/libclang/IndexingContext.h index b9234d88b3f..f5498e5292f 100644 --- a/tools/libclang/IndexingContext.h +++ b/tools/libclang/IndexingContext.h @@ -24,13 +24,18 @@ namespace clang { namespace cxindex { class IndexingContext; + class ScratchAlloc; + class AttrListInfo; struct EntityInfo : public CXIdxEntityInfo { const NamedDecl *Dcl; IndexingContext *IndexCtx; + llvm::IntrusiveRefCntPtr<AttrListInfo> AttrList; EntityInfo() { name = USR = 0; + attributes = 0; + numAttributes = 0; } }; @@ -195,14 +200,49 @@ struct IBOutletCollectionInfo : public AttrInfo { IBOutletCollectionInfo(CXCursor C, CXIdxLoc Loc, const Attr *A) : AttrInfo(CXIdxAttr_IBOutletCollection, C, Loc, A) { assert(C.kind == CXCursor_IBOutletCollectionAttr); + IBCollInfo.objcClass = 0; } + IBOutletCollectionInfo(const IBOutletCollectionInfo &other); + static bool classof(const AttrInfo *A) { return A->kind == CXIdxAttr_IBOutletCollection; } static bool classof(const IBOutletCollectionInfo *D) { return true; } }; +class AttrListInfo { + SmallVector<AttrInfo, 2> Attrs; + SmallVector<IBOutletCollectionInfo, 2> IBCollAttrs; + SmallVector<CXIdxAttrInfo *, 2> CXAttrs; + unsigned ref_cnt; + +public: + AttrListInfo(const Decl *D, + IndexingContext &IdxCtx, + ScratchAlloc &SA); + AttrListInfo(const AttrListInfo &other); + + const CXIdxAttrInfo *const *getAttrs() const { + if (CXAttrs.empty()) + return 0; + return CXAttrs.data(); + } + unsigned getNumAttrs() const { return (unsigned)CXAttrs.size(); } + + /// \brief Retain/Release only useful when we allocate a AttrListInfo from the + /// BumpPtrAllocator, and not from the stack; so that we keep a pointer + // in the EntityInfo + void Retain() { ++ref_cnt; } + void Release() { + assert (ref_cnt > 0 && "Reference count is already zero."); + if (--ref_cnt == 0) { + // Memory is allocated from a BumpPtrAllocator, no need to delete it. + this->~AttrListInfo(); + } + } +}; + struct RefFileOccurence { const FileEntry *File; const Decl *Dcl; @@ -233,24 +273,7 @@ class IndexingContext { llvm::BumpPtrAllocator StrScratch; unsigned StrAdapterCount; - - class StrAdapter { - IndexingContext &IdxCtx; - - public: - StrAdapter(IndexingContext &indexCtx) : IdxCtx(indexCtx) { - ++IdxCtx.StrAdapterCount; - } - - ~StrAdapter() { - --IdxCtx.StrAdapterCount; - if (IdxCtx.StrAdapterCount == 0) - IdxCtx.StrScratch.Reset(); - } - - const char *toCStr(StringRef Str); - const char *copyCStr(StringRef Str); - }; + friend class ScratchAlloc; struct ObjCProtocolListInfo { SmallVector<CXIdxObjCProtocolRefInfo, 4> ProtInfos; @@ -265,22 +288,7 @@ class IndexingContext { ObjCProtocolListInfo(const ObjCProtocolList &ProtList, IndexingContext &IdxCtx, - IndexingContext::StrAdapter &SA); - }; - - struct AttrListInfo { - SmallVector<AttrInfo, 2> Attrs; - SmallVector<IBOutletCollectionInfo, 2> IBCollAttrs; - SmallVector<CXIdxAttrInfo *, 2> CXAttrs; - - const CXIdxAttrInfo *const *getAttrs() const { - return CXAttrs.data(); - } - unsigned getNumAttrs() const { return (unsigned)CXAttrs.size(); } - - AttrListInfo(const Decl *D, - IndexingContext &IdxCtx, - IndexingContext::StrAdapter &SA); + ScratchAlloc &SA); }; struct CXXBasesListInfo { @@ -294,12 +302,14 @@ class IndexingContext { unsigned getNumBases() const { return (unsigned)CXBases.size(); } CXXBasesListInfo(const CXXRecordDecl *D, - IndexingContext &IdxCtx, IndexingContext::StrAdapter &SA); + IndexingContext &IdxCtx, ScratchAlloc &SA); private: SourceLocation getBaseLoc(const CXXBaseSpecifier &Base) const; }; + friend class AttrListInfo; + public: IndexingContext(CXClientData clientData, IndexerCallbacks &indexCallbacks, unsigned indexOptions, CXTranslationUnit cxTU) @@ -440,7 +450,7 @@ private: void getEntityInfo(const NamedDecl *D, EntityInfo &EntityInfo, - StrAdapter &SA); + ScratchAlloc &SA); void getContainerInfo(const DeclContext *DC, ContainerInfo &ContInfo); @@ -453,6 +463,29 @@ private: static bool shouldIgnoreIfImplicit(const NamedDecl *D); }; +class ScratchAlloc { + IndexingContext &IdxCtx; + +public: + explicit ScratchAlloc(IndexingContext &indexCtx) : IdxCtx(indexCtx) { + ++IdxCtx.StrAdapterCount; + } + + ~ScratchAlloc() { + --IdxCtx.StrAdapterCount; + if (IdxCtx.StrAdapterCount == 0) + IdxCtx.StrScratch.Reset(); + } + + const char *toCStr(StringRef Str); + const char *copyCStr(StringRef Str); + + template <typename T> + T *allocate() { + return IdxCtx.StrScratch.Allocate<T>(); + } +}; + }} // end clang::cxindex namespace llvm { -- GitLab