From b395c63b473bf1b3783bff371a993332e8c4c5e3 Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Fri, 18 Nov 2011 00:26:51 +0000 Subject: [PATCH] [libclang] Indexing API: -For indexDeclaration, also pass the declaration attributes as an array of cursors. -Rename CXIndexOpt_OneRefPerFile -> CXIndexOpt_SuppressRedundantRefs, and only pass a reference if a declaration/definition does not exist in the file. -Other fixes. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@144942 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang-c/Index.h | 39 +++- tools/c-index-test/c-index-test.c | 25 ++- tools/libclang/CXCursor.cpp | 13 +- tools/libclang/CXCursor.h | 6 +- tools/libclang/IndexBody.cpp | 21 +- tools/libclang/IndexDecl.cpp | 26 +++ tools/libclang/IndexTypeSourceInfo.cpp | 6 +- tools/libclang/Indexing.cpp | 53 +++-- tools/libclang/IndexingContext.cpp | 261 +++++++++++++++++-------- tools/libclang/IndexingContext.h | 109 ++++++++--- tools/libclang/libclang.exports | 1 + 11 files changed, 396 insertions(+), 164 deletions(-) diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index 09a01baba0..8434ccf8cf 100644 --- a/include/clang-c/Index.h +++ b/include/clang-c/Index.h @@ -4026,6 +4026,26 @@ typedef struct { const char *USR; } CXIdxEntityInfo; +typedef enum { + CXIdxAttr_Unexposed = 0, + CXIdxAttr_IBAction = 1, + CXIdxAttr_IBOutlet = 2, + CXIdxAttr_IBOutletCollection = 3 +} CXIdxAttrKind; + +typedef struct { + CXIdxAttrKind kind; + CXCursor cursor; + CXIdxLoc loc; +} CXIdxAttrInfo; + +typedef struct { + const CXIdxAttrInfo *attrInfo; + const CXIdxEntityInfo *objcClass; + CXCursor classCursor; + CXIdxLoc classLoc; +} CXIdxIBOutletCollectionAttrInfo; + typedef struct { const CXIdxEntityInfo *entityInfo; CXCursor cursor; @@ -4039,6 +4059,8 @@ typedef struct { * by the compiler, e.g. implicit objc methods for properties. */ int isImplicit; + const CXIdxAttrInfo *const *attributes; + unsigned numAttributes; } CXIdxDeclInfo; typedef struct { @@ -4095,9 +4117,10 @@ typedef enum { */ CXIdxEntityRef_Direct = 1, /** - * \brief A reference of an ObjC method via the dot syntax. + * \brief An implicit reference, e.g. a reference of an ObjC method via the + * dot syntax. */ - CXIdxEntityRef_ImplicitProperty = 2 + CXIdxEntityRef_Implicit = 2 } CXIdxEntityRefKind; /** @@ -4139,10 +4162,10 @@ typedef struct { int (*abortQuery)(CXClientData client_data, void *reserved); /** - * \brief Called when a diagnostic is emitted. + * \brief Called at the end of indexing; passes the complete diagnostic set. */ void (*diagnostic)(CXClientData client_data, - CXDiagnostic, void *reserved); + CXDiagnosticSet, void *reserved); CXIdxClientFile (*enteredMainFile)(CXClientData client_data, CXFile mainFile, void *reserved); @@ -4195,6 +4218,9 @@ clang_index_getObjCCategoryDeclInfo(const CXIdxDeclInfo *); CINDEX_LINKAGE const CXIdxObjCProtocolRefListInfo * clang_index_getObjCProtocolRefListInfo(const CXIdxDeclInfo *); +CINDEX_LINKAGE const CXIdxIBOutletCollectionAttrInfo * +clang_index_getIBOutletCollectionAttrInfo(const CXIdxAttrInfo *); + typedef enum { /** * \brief Used to indicate that no special indexing options are needed. @@ -4203,9 +4229,10 @@ typedef enum { /** * \brief Used to indicate that \see indexEntityReference should be invoked - * for only one reference of an entity per source file. + * for only one reference of an entity per source file that does not also + * include a declaration/definition of the entity. */ - CXIndexOpt_OneRefPerFile = 0x1 + CXIndexOpt_SuppressRedundantRefs = 0x1 } CXIndexOptFlags; /** diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c index c479278457..750b519e04 100644 --- a/tools/c-index-test/c-index-test.c +++ b/tools/c-index-test/c-index-test.c @@ -1741,6 +1741,7 @@ static void index_indexDeclaration(CXClientData client_data, const CXIdxObjCCategoryDeclInfo *CatInfo; const CXIdxObjCInterfaceDeclInfo *InterInfo; const CXIdxObjCProtocolRefListInfo *ProtoInfo; + unsigned i; index_data = (IndexData *)client_data; printEntityInfo("[indexDeclaration]", client_data, info->entityInfo); @@ -1755,6 +1756,13 @@ static void index_indexDeclaration(CXClientData client_data, printf(" | isContainer: %d", info->isContainer); printf(" | isImplicit: %d\n", info->isImplicit); + for (i = 0; i != info->numAttributes; ++i) { + printf(" : "); + const CXIdxAttrInfo *Attr = info->attributes[i]; + PrintCursor(Attr->cursor); + printf("\n"); + } + if (clang_index_isEntityObjCContainerKind(info->entityInfo->kind)) { const char *kindName = 0; CXIdxObjCContainerKind K = clang_index_getObjCContainerDeclInfo(info)->kind; @@ -1813,7 +1821,7 @@ static void index_indexEntityReference(CXClientData client_data, printf(" | refkind: "); switch (info->kind) { case CXIdxEntityRef_Direct: printf("direct"); break; - case CXIdxEntityRef_ImplicitProperty: printf("implicit prop"); break; + case CXIdxEntityRef_Implicit: printf("implicit"); break; } printf("\n"); } @@ -1833,6 +1841,7 @@ static int index_file(int argc, const char **argv) { const char *check_prefix; CXIndex CIdx; IndexData index_data; + unsigned index_opts; int result; check_prefix = 0; @@ -1854,9 +1863,12 @@ static int index_file(int argc, const char **argv) { index_data.first_check_printed = 0; index_data.fail_for_error = 0; + index_opts = 0; + if (getenv("CINDEXTEST_SUPPRESSREFS")) + index_opts |= CXIndexOpt_SuppressRedundantRefs; + result = clang_indexSourceFile(CIdx, &index_data, - &IndexCB,sizeof(IndexCB), - CXIndexOpt_OneRefPerFile, + &IndexCB,sizeof(IndexCB), index_opts, 0, argv, argc, 0, 0, 0, 0); if (index_data.fail_for_error) return -1; @@ -1869,6 +1881,7 @@ static int index_tu(int argc, const char **argv) { CXTranslationUnit TU; const char *check_prefix; IndexData index_data; + unsigned index_opts; int result; check_prefix = 0; @@ -1898,9 +1911,13 @@ static int index_tu(int argc, const char **argv) { index_data.first_check_printed = 0; index_data.fail_for_error = 0; + index_opts = 0; + if (getenv("CINDEXTEST_SUPPRESSREFS")) + index_opts |= CXIndexOpt_SuppressRedundantRefs; + result = clang_indexTranslationUnit(TU, &index_data, &IndexCB,sizeof(IndexCB), - CXIndexOpt_OneRefPerFile); + index_opts); if (index_data.fail_for_error) return -1; diff --git a/tools/libclang/CXCursor.cpp b/tools/libclang/CXCursor.cpp index 202a19254e..bba0928cea 100644 --- a/tools/libclang/CXCursor.cpp +++ b/tools/libclang/CXCursor.cpp @@ -535,12 +535,12 @@ cxcursor::getCursorTypeRef(CXCursor C) { reinterpret_cast(C.data[1]))); } -CXCursor cxcursor::MakeCursorTemplateRef(TemplateDecl *Template, +CXCursor cxcursor::MakeCursorTemplateRef(const TemplateDecl *Template, SourceLocation Loc, CXTranslationUnit TU) { assert(Template && TU && "Invalid arguments!"); void *RawLoc = reinterpret_cast(Loc.getRawEncoding()); - CXCursor C = { CXCursor_TemplateRef, 0, { Template, RawLoc, TU } }; + CXCursor C = { CXCursor_TemplateRef, 0, { (void*)Template, RawLoc, TU } }; return C; } @@ -552,13 +552,14 @@ cxcursor::getCursorTemplateRef(CXCursor C) { reinterpret_cast(C.data[1]))); } -CXCursor cxcursor::MakeCursorNamespaceRef(NamedDecl *NS, SourceLocation Loc, +CXCursor cxcursor::MakeCursorNamespaceRef(const NamedDecl *NS, + SourceLocation Loc, CXTranslationUnit TU) { assert(NS && (isa(NS) || isa(NS)) && TU && "Invalid arguments!"); void *RawLoc = reinterpret_cast(Loc.getRawEncoding()); - CXCursor C = { CXCursor_NamespaceRef, 0, { NS, RawLoc, TU } }; + CXCursor C = { CXCursor_NamespaceRef, 0, { (void*)NS, RawLoc, TU } }; return C; } @@ -570,12 +571,12 @@ cxcursor::getCursorNamespaceRef(CXCursor C) { reinterpret_cast(C.data[1]))); } -CXCursor cxcursor::MakeCursorMemberRef(FieldDecl *Field, SourceLocation Loc, +CXCursor cxcursor::MakeCursorMemberRef(const FieldDecl *Field, SourceLocation Loc, CXTranslationUnit TU) { assert(Field && TU && "Invalid arguments!"); void *RawLoc = reinterpret_cast(Loc.getRawEncoding()); - CXCursor C = { CXCursor_MemberRef, 0, { Field, RawLoc, TU } }; + CXCursor C = { CXCursor_MemberRef, 0, { (void*)Field, RawLoc, TU } }; return C; } diff --git a/tools/libclang/CXCursor.h b/tools/libclang/CXCursor.h index 8209cf4948..e54e43b2c8 100644 --- a/tools/libclang/CXCursor.h +++ b/tools/libclang/CXCursor.h @@ -95,7 +95,7 @@ CXCursor MakeCursorTypeRef(const TypeDecl *Type, SourceLocation Loc, std::pair getCursorTypeRef(CXCursor C); /// \brief Create a reference to a template at the given location. -CXCursor MakeCursorTemplateRef(TemplateDecl *Template, SourceLocation Loc, +CXCursor MakeCursorTemplateRef(const TemplateDecl *Template, SourceLocation Loc, CXTranslationUnit TU); /// \brief Unpack a TemplateRef cursor into the template it references and @@ -104,7 +104,7 @@ std::pair getCursorTemplateRef(CXCursor C); /// \brief Create a reference to a namespace or namespace alias at the given /// location. -CXCursor MakeCursorNamespaceRef(NamedDecl *NS, SourceLocation Loc, +CXCursor MakeCursorNamespaceRef(const NamedDecl *NS, SourceLocation Loc, CXTranslationUnit TU); /// \brief Unpack a NamespaceRef cursor into the namespace or namespace alias @@ -112,7 +112,7 @@ CXCursor MakeCursorNamespaceRef(NamedDecl *NS, SourceLocation Loc, std::pair getCursorNamespaceRef(CXCursor C); /// \brief Create a reference to a field at the given location. -CXCursor MakeCursorMemberRef(FieldDecl *Field, SourceLocation Loc, +CXCursor MakeCursorMemberRef(const FieldDecl *Field, SourceLocation Loc, CXTranslationUnit TU); /// \brief Unpack a MemberRef cursor into the field it references and the diff --git a/tools/libclang/IndexBody.cpp b/tools/libclang/IndexBody.cpp index ece1ed429c..60fe2cf021 100644 --- a/tools/libclang/IndexBody.cpp +++ b/tools/libclang/IndexBody.cpp @@ -10,6 +10,7 @@ #include "IndexingContext.h" #include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Analysis/Support/SaveAndRestore.h" using namespace clang; using namespace cxindex; @@ -19,10 +20,12 @@ namespace { class BodyIndexer : public RecursiveASTVisitor { IndexingContext &IndexCtx; const DeclContext *ParentDC; + bool InPseudoObject; + typedef RecursiveASTVisitor base; public: BodyIndexer(IndexingContext &indexCtx, const DeclContext *DC) - : IndexCtx(indexCtx), ParentDC(DC) { } + : IndexCtx(indexCtx), ParentDC(DC), InPseudoObject(false) { } bool shouldWalkTypesOfTypeLocs() const { return false; } @@ -48,8 +51,13 @@ public: } bool VisitObjCMessageExpr(ObjCMessageExpr *E) { + if (TypeSourceInfo *Cls = E->getClassReceiverTypeInfo()) + IndexCtx.indexTypeSourceInfo(Cls, 0, ParentDC); + if (ObjCMethodDecl *MD = E->getMethodDecl()) - IndexCtx.handleReference(MD, E->getSelectorStartLoc(), 0, ParentDC, E); + IndexCtx.handleReference(MD, E->getSelectorStartLoc(), 0, ParentDC, E, + InPseudoObject ? CXIdxEntityRef_Implicit + : CXIdxEntityRef_Direct); return true; } @@ -57,16 +65,21 @@ public: if (E->isImplicitProperty()) { if (ObjCMethodDecl *MD = E->getImplicitPropertyGetter()) IndexCtx.handleReference(MD, E->getLocation(), 0, ParentDC, E, - CXIdxEntityRef_ImplicitProperty); + CXIdxEntityRef_Implicit); if (ObjCMethodDecl *MD = E->getImplicitPropertySetter()) IndexCtx.handleReference(MD, E->getLocation(), 0, ParentDC, E, - CXIdxEntityRef_ImplicitProperty); + CXIdxEntityRef_Implicit); } else { IndexCtx.handleReference(E->getExplicitProperty(), E->getLocation(), 0, ParentDC, E); } return true; } + + bool TraversePseudoObjectExpr(PseudoObjectExpr *E) { + SaveAndRestore InPseudo(InPseudoObject, true); + return base::TraversePseudoObjectExpr(E); + } }; } // anonymous namespace diff --git a/tools/libclang/IndexDecl.cpp b/tools/libclang/IndexDecl.cpp index b2a45306dc..20b22052f7 100644 --- a/tools/libclang/IndexDecl.cpp +++ b/tools/libclang/IndexDecl.cpp @@ -159,6 +159,32 @@ public: IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D); return true; } + + bool VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { + ObjCPropertyDecl *PD = D->getPropertyDecl(); + IndexCtx.handleSynthesizedObjCProperty(D); + + if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) + return true; + assert(D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize); + + if (ObjCIvarDecl *IvarD = D->getPropertyIvarDecl()) { + if (!IvarD->getSynthesize()) + IndexCtx.handleReference(IvarD, D->getPropertyIvarDeclLoc(), 0, + D->getDeclContext()); + } + + if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) { + if (MD->isSynthesized()) + IndexCtx.handleSynthesizedObjCMethod(MD, D->getLocation()); + } + if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) { + if (MD->isSynthesized()) + IndexCtx.handleSynthesizedObjCMethod(MD, D->getLocation()); + } + + return true; + } }; } // anonymous namespace diff --git a/tools/libclang/IndexTypeSourceInfo.cpp b/tools/libclang/IndexTypeSourceInfo.cpp index 5aeee0d263..04ed329f3b 100644 --- a/tools/libclang/IndexTypeSourceInfo.cpp +++ b/tools/libclang/IndexTypeSourceInfo.cpp @@ -87,8 +87,8 @@ void IndexingContext::indexTypeLoc(TypeLoc TL, } void IndexingContext::indexTagDecl(const TagDecl *D) { - handleTagDecl(D); - if (D->isThisDeclarationADefinition()) { - indexDeclContext(D); + if (handleTagDecl(D)) { + if (D->isThisDeclarationADefinition()) + indexDeclContext(D); } } diff --git a/tools/libclang/Indexing.cpp b/tools/libclang/Indexing.cpp index 4540f9731d..5858faad2e 100644 --- a/tools/libclang/Indexing.cpp +++ b/tools/libclang/Indexing.cpp @@ -117,6 +117,10 @@ public: virtual void HandleTopLevelDecl(DeclGroupRef DG) { IndexCtx.indexDeclGroupRef(DG); + // FIXME: Indicate to parser to abort. +// if (IndexCtx.shouldAbort()) { +// +// } } /// \brief Handle the specified top-level declaration that occurred inside @@ -133,29 +137,9 @@ public: }; //===----------------------------------------------------------------------===// -// IndexingDiagnosticConsumer +// CaptureDiagnosticConsumer //===----------------------------------------------------------------------===// -class IndexingDiagnosticConsumer : public DiagnosticConsumer { - IndexingContext &IndexCtx; - -public: - explicit IndexingDiagnosticConsumer(IndexingContext &indexCtx) - : IndexCtx(indexCtx) {} - - virtual void HandleDiagnostic(DiagnosticsEngine::Level Level, - const Diagnostic &Info) { - // Default implementation (Warnings/errors count). - DiagnosticConsumer::HandleDiagnostic(Level, Info); - - IndexCtx.handleDiagnostic(StoredDiagnostic(Level, Info)); - } - - DiagnosticConsumer *clone(DiagnosticsEngine &Diags) const { - return new IgnoringDiagConsumer(); - } -}; - class CaptureDiagnosticConsumer : public DiagnosticConsumer { SmallVector Errors; public: @@ -187,8 +171,6 @@ public: virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { - CI.getDiagnostics().setClient(new IndexingDiagnosticConsumer(IndexCtx), - /*own=*/true); IndexCtx.setASTContext(CI.getASTContext()); Preprocessor &PP = CI.getPreprocessor(); PP.addPPCallbacks(new IndexPPCallbacks(PP, IndexCtx)); @@ -426,6 +408,8 @@ static void indexTranslationUnit(ASTUnit &Unit, IndexingContext &IdxCtx) { TLEnd = Unit.top_level_end(); TL != TLEnd; ++TL) { IdxCtx.indexTopLevelDecl(*TL); + if (IdxCtx.shouldAbort()) + return; } } else { @@ -433,17 +417,15 @@ static void indexTranslationUnit(ASTUnit &Unit, IndexingContext &IdxCtx) { for (TranslationUnitDecl::decl_iterator I = TUDecl->decls_begin(), E = TUDecl->decls_end(); I != E; ++I) { IdxCtx.indexTopLevelDecl(*I); + if (IdxCtx.shouldAbort()) + return; } } } static void indexDiagnostics(CXTranslationUnit TU, IndexingContext &IdxCtx) { - unsigned Num = clang_getNumDiagnostics(TU); - for (unsigned i = 0; i != Num; ++i) { - CXDiagnostic Diag = clang_getDiagnostic(TU, i); - IdxCtx.handleDiagnostic(Diag); - clang_disposeDiagnostic(Diag); - } + // FIXME: Create a CXDiagnosticSet from TU; + // IdxCtx.handleDiagnosticSet(Set); } static void clang_indexTranslationUnit_Impl(void *UserData) { @@ -568,6 +550,19 @@ clang_index_getObjCProtocolRefListInfo(const CXIdxDeclInfo *DInfo) { return 0; } +const CXIdxIBOutletCollectionAttrInfo * +clang_index_getIBOutletCollectionAttrInfo(const CXIdxAttrInfo *AInfo) { + if (!AInfo) + return 0; + + const AttrInfo *DI = static_cast(AInfo); + if (const IBOutletCollectionInfo * + IBInfo = dyn_cast(DI)) + return &IBInfo->IBCollInfo; + + return 0; +} + int clang_indexSourceFile(CXIndex CIdx, CXClientData client_data, IndexerCallbacks *index_callbacks, diff --git a/tools/libclang/IndexingContext.cpp b/tools/libclang/IndexingContext.cpp index f63fd3f103..d31ccdf061 100644 --- a/tools/libclang/IndexingContext.cpp +++ b/tools/libclang/IndexingContext.cpp @@ -13,6 +13,7 @@ #include "clang/Frontend/ASTUnit.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" using namespace clang; using namespace cxindex; @@ -42,6 +43,55 @@ IndexingContext::ObjCProtocolListInfo::ObjCProtocolListInfo( Prots.push_back(&ProtInfos[i]); } +IndexingContext::AttrListInfo::AttrListInfo(const Decl *D, + IndexingContext &IdxCtx, + StrAdapter &SA) { + for (AttrVec::const_iterator AttrI = D->attr_begin(), AttrE = D->attr_end(); + AttrI != AttrE; ++AttrI) { + const Attr *A = *AttrI; + CXCursor C = MakeCXCursor(A, const_cast(D), IdxCtx.CXTU); + CXIdxLoc Loc = IdxCtx.getIndexLoc(A->getLocation()); + switch (C.kind) { + default: + Attrs.push_back(AttrInfo(CXIdxAttr_Unexposed, C, Loc, A)); + break; + case CXCursor_IBActionAttr: + Attrs.push_back(AttrInfo(CXIdxAttr_IBAction, C, Loc, A)); + break; + case CXCursor_IBOutletAttr: + Attrs.push_back(AttrInfo(CXIdxAttr_IBOutlet, C, Loc, A)); + break; + case CXCursor_IBOutletCollectionAttr: + IBCollAttrs.push_back(IBOutletCollectionInfo(C, Loc, A)); + break; + } + } + + for (unsigned i = 0, e = IBCollAttrs.size(); i != e; ++i) { + IBOutletCollectionInfo &IBInfo = IBCollAttrs[i]; + CXAttrs.push_back(&IBInfo); + + const IBOutletCollectionAttr * + IBAttr = cast(IBInfo.A); + IBInfo.IBCollInfo.attrInfo = &IBInfo; + IBInfo.IBCollInfo.classLoc = IdxCtx.getIndexLoc(IBAttr->getInterfaceLoc()); + IBInfo.IBCollInfo.objcClass = 0; + IBInfo.IBCollInfo.classCursor = clang_getNullCursor(); + QualType Ty = IBAttr->getInterface(); + if (const ObjCInterfaceType *InterTy = Ty->getAs()) { + if (const ObjCInterfaceDecl *InterD = InterTy->getInterface()) { + IdxCtx.getEntityInfo(InterD, IBInfo.CXClassInfo, SA); + IBInfo.IBCollInfo.objcClass = &IBInfo.CXClassInfo; + IBInfo.IBCollInfo.classCursor = MakeCursorObjCClassRef(InterD, + IBAttr->getInterfaceLoc(), IdxCtx.CXTU); + } + } + } + + for (unsigned i = 0, e = Attrs.size(); i != e; ++i) + CXAttrs.push_back(&Attrs[i]); +} + const char *IndexingContext::StrAdapter::toCStr(StringRef Str) { if (Str.empty()) return ""; @@ -57,6 +107,12 @@ void IndexingContext::setASTContext(ASTContext &ctx) { static_cast(CXTU->TUData)->setASTContext(&ctx); } +bool IndexingContext::shouldAbort() { + if (!CB.abortQuery) + return false; + return CB.abortQuery(ClientData, 0); +} + void IndexingContext::enteredMainFile(const FileEntry *File) { if (File && CB.enteredMainFile) { CXIdxClientFile idxFile = CB.enteredMainFile(ClientData, (CXFile)File, 0); @@ -87,90 +143,90 @@ void IndexingContext::startedTranslationUnit() { addContainerInMap(Ctx->getTranslationUnitDecl(), idxCont); } -void IndexingContext::handleDiagnostic(const StoredDiagnostic &StoredDiag) { +void IndexingContext::handleDiagnosticSet(CXDiagnostic CXDiagSet) { if (!CB.diagnostic) return; - CXStoredDiagnostic CXDiag(StoredDiag, Ctx->getLangOptions()); - CB.diagnostic(ClientData, &CXDiag, 0); + CB.diagnostic(ClientData, CXDiagSet, 0); } -void IndexingContext::handleDiagnostic(CXDiagnostic CXDiag) { - if (!CB.diagnostic) - return; - - CB.diagnostic(ClientData, CXDiag, 0); -} - -void IndexingContext::handleDecl(const NamedDecl *D, +bool IndexingContext::handleDecl(const NamedDecl *D, SourceLocation Loc, CXCursor Cursor, DeclInfo &DInfo) { if (!CB.indexDeclaration || !D) - return; + return false; StrAdapter SA(*this); getEntityInfo(D, DInfo.CXEntInfo, SA); if (!DInfo.CXEntInfo.USR || Loc.isInvalid()) - return; + return false; + markEntityOccurrenceInFile(D, Loc); + DInfo.entityInfo = &DInfo.CXEntInfo; DInfo.cursor = Cursor; DInfo.loc = getIndexLoc(Loc); DInfo.container = getIndexContainer(D); DInfo.isImplicit = D->isImplicit(); + AttrListInfo AttrList(D, *this, SA); + DInfo.attributes = AttrList.getAttrs(); + DInfo.numAttributes = AttrList.getNumAttrs(); + CXIdxClientContainer clientCont = 0; CXIdxDeclOut DeclOut = { DInfo.isContainer ? &clientCont : 0 }; CB.indexDeclaration(ClientData, &DInfo, &DeclOut); if (DInfo.isContainer) addContainerInMap(cast(D), clientCont); + + return true; } -void IndexingContext::handleObjCContainer(const ObjCContainerDecl *D, +bool IndexingContext::handleObjCContainer(const ObjCContainerDecl *D, SourceLocation Loc, CXCursor Cursor, ObjCContainerDeclInfo &ContDInfo) { ContDInfo.ObjCContDeclInfo.declInfo = &ContDInfo; - handleDecl(D, Loc, Cursor, ContDInfo); + return handleDecl(D, Loc, Cursor, ContDInfo); } -void IndexingContext::handleFunction(const FunctionDecl *D) { +bool IndexingContext::handleFunction(const FunctionDecl *D) { DeclInfo DInfo(!D->isFirstDeclaration(), D->isThisDeclarationADefinition(), D->isThisDeclarationADefinition()); - handleDecl(D, D->getLocation(), getCursor(D), DInfo); + return handleDecl(D, D->getLocation(), getCursor(D), DInfo); } -void IndexingContext::handleVar(const VarDecl *D) { +bool IndexingContext::handleVar(const VarDecl *D) { DeclInfo DInfo(!D->isFirstDeclaration(), D->isThisDeclarationADefinition(), /*isContainer=*/false); - handleDecl(D, D->getLocation(), getCursor(D), DInfo); + return handleDecl(D, D->getLocation(), getCursor(D), DInfo); } -void IndexingContext::handleField(const FieldDecl *D) { +bool IndexingContext::handleField(const FieldDecl *D) { DeclInfo DInfo(/*isRedeclaration=*/false, /*isDefinition=*/true, /*isContainer=*/false); - handleDecl(D, D->getLocation(), getCursor(D), DInfo); + return handleDecl(D, D->getLocation(), getCursor(D), DInfo); } -void IndexingContext::handleEnumerator(const EnumConstantDecl *D) { +bool IndexingContext::handleEnumerator(const EnumConstantDecl *D) { DeclInfo DInfo(/*isRedeclaration=*/false, /*isDefinition=*/true, /*isContainer=*/false); - handleDecl(D, D->getLocation(), getCursor(D), DInfo); + return handleDecl(D, D->getLocation(), getCursor(D), DInfo); } -void IndexingContext::handleTagDecl(const TagDecl *D) { +bool IndexingContext::handleTagDecl(const TagDecl *D) { DeclInfo DInfo(!D->isFirstDeclaration(), D->isThisDeclarationADefinition(), D->isThisDeclarationADefinition()); - handleDecl(D, D->getLocation(), getCursor(D), DInfo); + return handleDecl(D, D->getLocation(), getCursor(D), DInfo); } -void IndexingContext::handleTypedef(const TypedefDecl *D) { +bool IndexingContext::handleTypedef(const TypedefDecl *D) { DeclInfo DInfo(!D->isFirstDeclaration(), /*isDefinition=*/true, /*isContainer=*/false); - handleDecl(D, D->getLocation(), getCursor(D), DInfo); + return handleDecl(D, D->getLocation(), getCursor(D), DInfo); } -void IndexingContext::handleObjCClass(const ObjCClassDecl *D) { +bool IndexingContext::handleObjCClass(const ObjCClassDecl *D) { const ObjCClassDecl::ObjCClassRef *Ref = D->getForwardDecl(); ObjCInterfaceDecl *IFaceD = Ref->getInterface(); SourceLocation Loc = Ref->getLocation(); @@ -178,11 +234,11 @@ void IndexingContext::handleObjCClass(const ObjCClassDecl *D) { ObjCContainerDeclInfo ContDInfo(/*isForwardRef=*/true, isRedeclaration, /*isImplementation=*/false); - handleObjCContainer(IFaceD, Loc, MakeCursorObjCClassRef(IFaceD, Loc, CXTU), - ContDInfo); + return handleObjCContainer(IFaceD, Loc, + MakeCursorObjCClassRef(IFaceD, Loc, CXTU), ContDInfo); } -void IndexingContext::handleObjCInterface(const ObjCInterfaceDecl *D) { +bool IndexingContext::handleObjCInterface(const ObjCInterfaceDecl *D) { StrAdapter SA(*this); CXIdxBaseClassInfo BaseClass; @@ -204,44 +260,45 @@ void IndexingContext::handleObjCInterface(const ObjCInterfaceDecl *D) { InterInfo.ObjCInterDeclInfo.superInfo = D->getSuperClass() ? &BaseClass : 0; InterInfo.ObjCInterDeclInfo.protocols = &InterInfo.ObjCProtoListInfo; - handleObjCContainer(D, D->getLocation(), getCursor(D), InterInfo); + return handleObjCContainer(D, D->getLocation(), getCursor(D), InterInfo); } -void IndexingContext::handleObjCImplementation( +bool IndexingContext::handleObjCImplementation( const ObjCImplementationDecl *D) { ObjCContainerDeclInfo ContDInfo(/*isForwardRef=*/false, /*isRedeclaration=*/true, /*isImplementation=*/true); - handleObjCContainer(D, D->getLocation(), getCursor(D), ContDInfo); + return handleObjCContainer(D, D->getLocation(), getCursor(D), ContDInfo); } -void IndexingContext::handleObjCForwardProtocol(const ObjCProtocolDecl *D, +bool IndexingContext::handleObjCForwardProtocol(const ObjCProtocolDecl *D, SourceLocation Loc, bool isRedeclaration) { ObjCContainerDeclInfo ContDInfo(/*isForwardRef=*/true, isRedeclaration, /*isImplementation=*/false); - handleObjCContainer(D, Loc, MakeCursorObjCProtocolRef(D, Loc, CXTU), - ContDInfo); + return handleObjCContainer(D, Loc, MakeCursorObjCProtocolRef(D, Loc, CXTU), + ContDInfo); } -void IndexingContext::handleObjCProtocol(const ObjCProtocolDecl *D) { +bool IndexingContext::handleObjCProtocol(const ObjCProtocolDecl *D) { StrAdapter SA(*this); ObjCProtocolListInfo ProtListInfo(D->getReferencedProtocols(), *this, SA); ObjCProtocolDeclInfo ProtInfo(D); ProtInfo.ObjCProtoRefListInfo = ProtListInfo.getListInfo(); - handleObjCContainer(D, D->getLocation(), getCursor(D), ProtInfo); + return handleObjCContainer(D, D->getLocation(), getCursor(D), ProtInfo); } -void IndexingContext::handleObjCCategory(const ObjCCategoryDecl *D) { +bool IndexingContext::handleObjCCategory(const ObjCCategoryDecl *D) { ObjCCategoryDeclInfo CatDInfo(/*isImplementation=*/false); CXIdxEntityInfo ClassEntity; StrAdapter SA(*this); const ObjCInterfaceDecl *IFaceD = D->getClassInterface(); SourceLocation ClassLoc = D->getLocation(); - SourceLocation CategoryLoc = D->getCategoryNameLoc(); + SourceLocation CategoryLoc = D->IsClassExtension() ? ClassLoc + : D->getCategoryNameLoc(); getEntityInfo(IFaceD, ClassEntity, SA); CatDInfo.ObjCCatDeclInfo.containerInfo = &CatDInfo.ObjCContDeclInfo; @@ -254,10 +311,10 @@ void IndexingContext::handleObjCCategory(const ObjCCategoryDecl *D) { CatDInfo.ObjCCatDeclInfo.classCursor = clang_getNullCursor(); } CatDInfo.ObjCCatDeclInfo.classLoc = getIndexLoc(ClassLoc); - handleObjCContainer(D, CategoryLoc, getCursor(D), CatDInfo); + return handleObjCContainer(D, CategoryLoc, getCursor(D), CatDInfo); } -void IndexingContext::handleObjCCategoryImpl(const ObjCCategoryImplDecl *D) { +bool IndexingContext::handleObjCCategoryImpl(const ObjCCategoryImplDecl *D) { const ObjCCategoryDecl *CatD = D->getCategoryDecl(); ObjCCategoryDeclInfo CatDInfo(/*isImplementation=*/true); CXIdxEntityInfo ClassEntity; @@ -277,69 +334,78 @@ void IndexingContext::handleObjCCategoryImpl(const ObjCCategoryImplDecl *D) { CatDInfo.ObjCCatDeclInfo.classCursor = clang_getNullCursor(); } CatDInfo.ObjCCatDeclInfo.classLoc = getIndexLoc(ClassLoc); - handleObjCContainer(D, CategoryLoc, getCursor(D), CatDInfo); + return handleObjCContainer(D, CategoryLoc, getCursor(D), CatDInfo); } -void IndexingContext::handleObjCMethod(const ObjCMethodDecl *D) { +bool IndexingContext::handleObjCMethod(const ObjCMethodDecl *D) { DeclInfo DInfo(!D->isCanonicalDecl(), D->isThisDeclarationADefinition(), D->isThisDeclarationADefinition()); - handleDecl(D, D->getLocation(), getCursor(D), DInfo); + return handleDecl(D, D->getLocation(), getCursor(D), DInfo); +} + +bool IndexingContext::handleSynthesizedObjCProperty( + const ObjCPropertyImplDecl *D) { + ObjCPropertyDecl *PD = D->getPropertyDecl(); + return handleReference(PD, D->getLocation(), getCursor(D), 0, D->getDeclContext()); } -void IndexingContext::handleObjCProperty(const ObjCPropertyDecl *D) { +bool IndexingContext::handleSynthesizedObjCMethod(const ObjCMethodDecl *D, + SourceLocation Loc) { + DeclInfo DInfo(/*isRedeclaration=*/true, /*isDefinition=*/true, + /*isContainer=*/false); + return handleDecl(D, Loc, getCursor(D), DInfo); +} + +bool IndexingContext::handleObjCProperty(const ObjCPropertyDecl *D) { DeclInfo DInfo(/*isRedeclaration=*/false, /*isDefinition=*/false, /*isContainer=*/false); - handleDecl(D, D->getLocation(), getCursor(D), DInfo); + return handleDecl(D, D->getLocation(), getCursor(D), DInfo); } -void IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc, +bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc, const NamedDecl *Parent, const DeclContext *DC, const Expr *E, CXIdxEntityRefKind Kind) { if (!D) - return; + return false; + + CXCursor Cursor = E ? MakeCXCursor(const_cast(E), + const_cast(cast(DC)), CXTU) + : getRefCursor(D, Loc); + return handleReference(D, Loc, Cursor, Parent, DC, E, Kind); +} + +bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc, + CXCursor Cursor, + const NamedDecl *Parent, + const DeclContext *DC, + const Expr *E, + CXIdxEntityRefKind Kind) { + if (!D) + return false; if (D->getParentFunctionOrMethod()) - return; + return false; if (Loc.isInvalid()) - return; + return false; if (!CB.indexEntityReference) - return; + return false; if (isNotFromSourceFile(D->getLocation())) - return; - - D = getEntityDecl(D); + return false; StrAdapter SA(*this); CXIdxEntityInfo RefEntity, ParentEntity; getEntityInfo(D, RefEntity, SA); if (!RefEntity.USR) - return; + return false; getEntityInfo(Parent, ParentEntity, SA); - if (onlyOneRefPerFile()) { - SourceManager &SM = Ctx->getSourceManager(); - SourceLocation FileLoc = SM.getFileLoc(Loc); - - std::pair LocInfo = SM.getDecomposedLoc(Loc); - FileID FID = LocInfo.first; - if (FID.isInvalid()) - return; - - const FileEntry *FE = SM.getFileEntryForID(FID); - if (!FE) - return; - RefFileOccurence RefOccur(FE, D); - std::pair::iterator, bool> - res = RefFileOccurences.insert(RefOccur); - if (!res.second) - return; // already in map. + if (suppressRefs()) { + if (markEntityOccurrenceInFile(D, Loc)) + return false; // already occurred. } - CXCursor Cursor = E ? MakeCXCursor(const_cast(E), - const_cast(cast(DC)), CXTU) - : getRefCursor(D, Loc); CXIdxEntityRefInfo Info = { Cursor, getIndexLoc(Loc), &RefEntity, @@ -347,6 +413,7 @@ void IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc, getIndexContainerForDC(DC), Kind }; CB.indexEntityReference(ClientData, &Info); + return true; } bool IndexingContext::isNotFromSourceFile(SourceLocation Loc) const { @@ -375,15 +442,34 @@ void IndexingContext::addContainerInMap(const DeclContext *DC, ContainerMap.erase(I); } +bool IndexingContext::markEntityOccurrenceInFile(const NamedDecl *D, + SourceLocation Loc) { + SourceManager &SM = Ctx->getSourceManager(); + SourceLocation FileLoc = SM.getFileLoc(Loc); + D = getEntityDecl(D); + + std::pair LocInfo = SM.getDecomposedLoc(Loc); + FileID FID = LocInfo.first; + if (FID.isInvalid()) + return true; + + const FileEntry *FE = SM.getFileEntryForID(FID); + if (!FE) + return true; + RefFileOccurence RefOccur(FE, D); + std::pair::iterator, bool> + res = RefFileOccurences.insert(RefOccur); + if (!res.second) + return true; // already in map. + + return false; +} + const NamedDecl *IndexingContext::getEntityDecl(const NamedDecl *D) const { assert(D); D = cast(D->getCanonicalDecl()); - if (const ObjCCategoryDecl *Cat = dyn_cast(D)) { - if (Cat->IsClassExtension()) - return getEntityDecl(Cat->getClassInterface()); - - } else if (const ObjCImplementationDecl * + if (const ObjCImplementationDecl * ImplD = dyn_cast(D)) { return getEntityDecl(ImplD->getClassInterface()); @@ -563,7 +649,14 @@ CXCursor IndexingContext::getRefCursor(const NamedDecl *D, SourceLocation Loc) { return MakeCursorObjCClassRef(ID, Loc, CXTU); if (const ObjCProtocolDecl *PD = dyn_cast(D)) return MakeCursorObjCProtocolRef(PD, Loc, CXTU); - - //assert(0 && "not yet"); + if (const TemplateDecl *Template = dyn_cast(D)) + return MakeCursorTemplateRef(Template, Loc, CXTU); + if (const NamespaceDecl *Namespace = dyn_cast(D)) + return MakeCursorNamespaceRef(Namespace, Loc, CXTU); + if (const NamespaceAliasDecl *Namespace = dyn_cast(D)) + return MakeCursorNamespaceRef(Namespace, Loc, CXTU); + if (const FieldDecl *Field = dyn_cast(D)) + return MakeCursorMemberRef(Field, Loc, CXTU); + return clang_getNullCursor(); } diff --git a/tools/libclang/IndexingContext.h b/tools/libclang/IndexingContext.h index 35545d281f..a18d8c6f8b 100644 --- a/tools/libclang/IndexingContext.h +++ b/tools/libclang/IndexingContext.h @@ -40,6 +40,8 @@ struct DeclInfo : public CXIdxDeclInfo { this->isRedeclaration = isRedeclaration; this->isDefinition = isDefinition; this->isContainer = isContainer; + attributes = 0; + numAttributes = 0; } DeclInfo(DInfoKind K, bool isRedeclaration, bool isDefinition, bool isContainer) @@ -47,6 +49,8 @@ struct DeclInfo : public CXIdxDeclInfo { this->isRedeclaration = isRedeclaration; this->isDefinition = isDefinition; this->isContainer = isContainer; + attributes = 0; + numAttributes = 0; } static bool classof(const DeclInfo *) { return true; } @@ -133,6 +137,34 @@ struct ObjCCategoryDeclInfo : public ObjCContainerDeclInfo { static bool classof(const ObjCCategoryDeclInfo *D) { return true; } }; +struct AttrInfo : public CXIdxAttrInfo { + const Attr *A; + + AttrInfo(CXIdxAttrKind Kind, CXCursor C, CXIdxLoc Loc, const Attr *A) { + kind = Kind; + cursor = C; + loc = Loc; + this->A = A; + } + + static bool classof(const AttrInfo *) { return true; } +}; + +struct IBOutletCollectionInfo : public AttrInfo { + CXIdxEntityInfo CXClassInfo; + CXIdxIBOutletCollectionAttrInfo IBCollInfo; + + IBOutletCollectionInfo(CXCursor C, CXIdxLoc Loc, const Attr *A) : + AttrInfo(CXIdxAttr_IBOutletCollection, C, Loc, A) { + assert(C.kind == CXCursor_IBOutletCollectionAttr); + } + + static bool classof(const AttrInfo *A) { + return A->kind == CXIdxAttr_IBOutletCollection; + } + static bool classof(const IBOutletCollectionInfo *D) { return true; } +}; + struct RefFileOccurence { const FileEntry *File; const Decl *Dcl; @@ -193,7 +225,7 @@ class IndexingContext { SmallVector ProtEntities; SmallVector Prots; - CXIdxObjCProtocolRefListInfo getListInfo() { + CXIdxObjCProtocolRefListInfo getListInfo() const { CXIdxObjCProtocolRefListInfo Info = { Prots.data(), (unsigned)Prots.size() }; return Info; @@ -204,6 +236,21 @@ class IndexingContext { IndexingContext::StrAdapter &SA); }; + struct AttrListInfo { + SmallVector Attrs; + SmallVector IBCollAttrs; + SmallVector 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); +}; + public: IndexingContext(CXClientData clientData, IndexerCallbacks &indexCallbacks, unsigned indexOptions, CXTranslationUnit cxTU) @@ -214,10 +261,12 @@ public: void setASTContext(ASTContext &ctx); - bool onlyOneRefPerFile() const { - return IndexOptions & CXIndexOpt_OneRefPerFile; + bool suppressRefs() const { + return IndexOptions & CXIndexOpt_SuppressRedundantRefs; } + bool shouldAbort(); + void enteredMainFile(const FileEntry *File); void ppIncludedFile(SourceLocation hashLoc, @@ -240,39 +289,47 @@ public: void indexBody(const Stmt *S, const DeclContext *DC); - void handleDiagnostic(const StoredDiagnostic &StoredDiag); - void handleDiagnostic(CXDiagnostic CXDiag); + void handleDiagnosticSet(CXDiagnosticSet CXDiagSet); - void handleFunction(const FunctionDecl *FD); + bool handleFunction(const FunctionDecl *FD); - void handleVar(const VarDecl *D); + bool handleVar(const VarDecl *D); - void handleField(const FieldDecl *D); + bool handleField(const FieldDecl *D); - void handleEnumerator(const EnumConstantDecl *D); + bool handleEnumerator(const EnumConstantDecl *D); - void handleTagDecl(const TagDecl *D); + bool handleTagDecl(const TagDecl *D); - void handleTypedef(const TypedefDecl *D); + bool handleTypedef(const TypedefDecl *D); - void handleObjCClass(const ObjCClassDecl *D); - void handleObjCInterface(const ObjCInterfaceDecl *D); - void handleObjCImplementation(const ObjCImplementationDecl *D); + bool handleObjCClass(const ObjCClassDecl *D); + bool handleObjCInterface(const ObjCInterfaceDecl *D); + bool handleObjCImplementation(const ObjCImplementationDecl *D); - void handleObjCForwardProtocol(const ObjCProtocolDecl *D, + bool handleObjCForwardProtocol(const ObjCProtocolDecl *D, SourceLocation Loc, bool isRedeclaration); - void handleObjCProtocol(const ObjCProtocolDecl *D); + bool handleObjCProtocol(const ObjCProtocolDecl *D); + + bool handleObjCCategory(const ObjCCategoryDecl *D); + bool handleObjCCategoryImpl(const ObjCCategoryImplDecl *D); - void handleObjCCategory(const ObjCCategoryDecl *D); - void handleObjCCategoryImpl(const ObjCCategoryImplDecl *D); + bool handleObjCMethod(const ObjCMethodDecl *D); - void handleObjCMethod(const ObjCMethodDecl *D); + bool handleSynthesizedObjCProperty(const ObjCPropertyImplDecl *D); + bool handleSynthesizedObjCMethod(const ObjCMethodDecl *D, SourceLocation Loc); - void handleObjCProperty(const ObjCPropertyDecl *D); + bool handleObjCProperty(const ObjCPropertyDecl *D); - void handleReference(const NamedDecl *D, SourceLocation Loc, + bool handleReference(const NamedDecl *D, SourceLocation Loc, CXCursor Cursor, + const NamedDecl *Parent, + const DeclContext *DC, + const Expr *E = 0, + CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct); + + bool handleReference(const NamedDecl *D, SourceLocation Loc, const NamedDecl *Parent, const DeclContext *DC, const Expr *E = 0, @@ -292,16 +349,18 @@ public: unsigned *line, unsigned *column, unsigned *offset); private: - void handleDecl(const NamedDecl *D, + bool handleDecl(const NamedDecl *D, SourceLocation Loc, CXCursor Cursor, DeclInfo &DInfo); - void handleObjCContainer(const ObjCContainerDecl *D, + bool handleObjCContainer(const ObjCContainerDecl *D, SourceLocation Loc, CXCursor Cursor, ObjCContainerDeclInfo &ContDInfo); void addContainerInMap(const DeclContext *DC, CXIdxClientContainer container); + bool markEntityOccurrenceInFile(const NamedDecl *D, SourceLocation Loc); + const NamedDecl *getEntityDecl(const NamedDecl *D) const; CXIdxClientContainer getIndexContainer(const NamedDecl *D) const { @@ -319,8 +378,8 @@ private: CXIdxEntityInfo &EntityInfo, StrAdapter &SA); - CXCursor getCursor(const NamedDecl *D) { - return cxcursor::MakeCXCursor(const_cast(D), CXTU); + CXCursor getCursor(const Decl *D) { + return cxcursor::MakeCXCursor(const_cast(D), CXTU); } CXCursor getRefCursor(const NamedDecl *D, SourceLocation Loc); diff --git a/tools/libclang/libclang.exports b/tools/libclang/libclang.exports index 870f84c253..2cb5436c84 100644 --- a/tools/libclang/libclang.exports +++ b/tools/libclang/libclang.exports @@ -135,6 +135,7 @@ clang_getTranslationUnitSpelling clang_getTypeDeclaration clang_getTypeKindSpelling clang_hashCursor +clang_index_getIBOutletCollectionAttrInfo clang_index_getObjCCategoryDeclInfo clang_index_getObjCContainerDeclInfo clang_index_getObjCInterfaceDeclInfo -- 2.40.0