forked from OSchip/llvm-project
[libclang] Indexing API: provide an attribute list inside CXIdxEntityInfo
so that we can access the attributes of an entity for a reference. llvm-svn: 146616
This commit is contained in:
parent
41cfce25fe
commit
4d873b725e
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue