[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
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h
index 9da6b23..d9d027e 100644
--- a/include/clang-c/Index.h
+++ b/include/clang-c/Index.h
@@ -4171,19 +4171,6 @@
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,
@@ -4198,6 +4185,21 @@
} 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;
CXCursor classCursor;
diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c
index fdc88a0..d46f2dc 100644
--- a/tools/c-index-test/c-index-test.c
+++ b/tools/c-index-test/c-index-test.c
@@ -1684,6 +1684,7 @@
const CXIdxEntityInfo *info) {
const char *name;
IndexData *index_data;
+ unsigned i;
index_data = (IndexData *)client_data;
printCheck(index_data);
@@ -1701,6 +1702,12 @@
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 8d27d85..23d8e7e 100644
--- a/tools/libclang/IndexingContext.cpp
+++ b/tools/libclang/IndexingContext.cpp
@@ -22,7 +22,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
if (!CB.ppIncludedFile)
return;
- StrAdapter SA(*this);
+ ScratchAlloc SA(*this);
CXIdxIncludedFileInfo Info = { getIndexLoc(hashLoc),
SA.toCStr(filename),
(CXFile)File,
@@ -226,7 +259,7 @@
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::handleObjCInterface(const ObjCInterfaceDecl *D) {
- StrAdapter SA(*this);
+ ScratchAlloc SA(*this);
CXIdxBaseClassInfo BaseClass;
EntityInfo BaseEntity;
@@ -366,7 +399,7 @@
}
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::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 @@
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 @@
return false; // already occurred.
}
- StrAdapter SA(*this);
+ ScratchAlloc SA(*this);
EntityInfo RefEntity, ParentEntity;
getEntityInfo(D, RefEntity, SA);
if (!RefEntity.USR)
@@ -586,7 +619,7 @@
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::getEntityInfo(const NamedDecl *D,
EntityInfo &EntityInfo,
- StrAdapter &SA) {
+ ScratchAlloc &SA) {
if (!D)
return;
@@ -743,6 +776,14 @@
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 b9234d8..f5498e5 100644
--- a/tools/libclang/IndexingContext.h
+++ b/tools/libclang/IndexingContext.h
@@ -24,13 +24,18 @@
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 @@
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 @@
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 @@
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 @@
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 @@
void getEntityInfo(const NamedDecl *D,
EntityInfo &EntityInfo,
- StrAdapter &SA);
+ ScratchAlloc &SA);
void getContainerInfo(const DeclContext *DC, ContainerInfo &ContInfo);
@@ -453,6 +463,29 @@
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 {