Index: include/clang-c/Index.h =================================================================== --- include/clang-c/Index.h +++ include/clang-c/Index.h @@ -32,7 +32,7 @@ * compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable. */ #define CINDEX_VERSION_MAJOR 0 -#define CINDEX_VERSION_MINOR 47 +#define CINDEX_VERSION_MINOR 48 #define CINDEX_VERSION_ENCODE(major, minor) ( \ ((major) * 10000) \ @@ -6092,6 +6092,9 @@ /** * \brief Data for IndexerCallbacks#indexEntityReference. + * + * This may be deprecated in a future version as this duplicates + * the \c CXSymbolRole_Implicit bit in \c CXSymbolRole. */ typedef enum { /** @@ -6106,6 +6109,25 @@ } CXIdxEntityRefKind; /** + * \brief Roles that are attributed to symbol occurrences. + * + * Internal: this currently mirrors low 9 bits of clang::index::SymbolRole with + * higher bits zeroed. These high bits may be exposed in the future. + */ +typedef enum { + CXSymbolRole_None = 0, + CXSymbolRole_Declaration = 1 << 0, + CXSymbolRole_Definition = 1 << 1, + CXSymbolRole_Reference = 1 << 2, + CXSymbolRole_Read = 1 << 3, + CXSymbolRole_Write = 1 << 4, + CXSymbolRole_Call = 1 << 5, + CXSymbolRole_Dynamic = 1 << 6, + CXSymbolRole_AddressOf = 1 << 7, + CXSymbolRole_Implicit = 1 << 8 +} CXSymbolRole; + +/** * \brief Data for IndexerCallbacks#indexEntityReference. */ typedef struct { @@ -6135,6 +6157,10 @@ * \brief Lexical container context of the reference. */ const CXIdxContainerInfo *container; + /** + * \brief Sets of symbol roles of the reference. + */ + CXSymbolRole role; } CXIdxEntityRefInfo; /** Index: include/clang/Index/IndexSymbol.h =================================================================== --- include/clang/Index/IndexSymbol.h +++ include/clang/Index/IndexSymbol.h @@ -89,6 +89,8 @@ static const unsigned SymbolPropertyBitNum = 8; /// Set of roles that are attributed to symbol occurrences. +/// +/// Low 9 bits of clang-c/include/Index.h CXSymbolRole mirrors this enum. enum class SymbolRole : uint32_t { Declaration = 1 << 0, Definition = 1 << 1, Index: test/Index/index-refs.cpp =================================================================== --- test/Index/index-refs.cpp +++ test/Index/index-refs.cpp @@ -67,6 +67,9 @@ void foo5() { struct S2 s = { .y = 1, .x = 4}; + s.y = s.x + 1; + (void)&foo3; + foo4(s.y); } int ginitlist[] = {EnumVal}; @@ -105,7 +108,7 @@ // CHECK: [indexDeclaration]: kind: c++-class-template | name: TS | {{.*}} | loc: 47:8 // CHECK-NEXT: [indexDeclaration]: kind: struct-template-partial-spec | name: TS | USR: c:@SP>1#T@TS>#t0.0#I | {{.*}} | loc: 50:8 // CHECK-NEXT: [indexDeclaration]: kind: typedef | name: MyInt | USR: c:index-refs.cpp@SP>1#T@TS>#t0.0#I@T@MyInt | {{.*}} | loc: 51:15 | semantic-container: [TS:50:8] | lexical-container: [TS:50:8] -// CHECK-NEXT: [indexEntityReference]: kind: c++-class-template | name: TS | USR: c:@ST>2#T#T@TS | lang: C++ | cursor: TemplateRef=TS:47:8 | loc: 50:8 | :: <> | container: [TU] | refkind: direct +// CHECK-NEXT: [indexEntityReference]: kind: c++-class-template | name: TS | USR: c:@ST>2#T#T@TS | lang: C++ | cursor: TemplateRef=TS:47:8 | loc: 50:8 | :: <> | container: [TU] | refkind: direct | role: ref /* when indexing implicit instantiations [indexDeclaration]: kind: struct-template-spec | name: TS | USR: c:@S@TS>#I | {{.*}} | loc: 50:8 [indexDeclaration]: kind: typedef | name: MyInt | USR: c:index-refs.cpp@593@S@TS>#I@T@MyInt | {{.*}} | loc: 51:15 | semantic-container: [TS:50:8] | lexical-container: [TS:50:8] @@ -117,7 +120,7 @@ // CHECK-NEXT: [indexEntityReference]: kind: c++-class-template | name: TS | USR: c:@ST>2#T#T@TS | {{.*}} | loc: 55:3 // CHECK: [indexEntityReference]: kind: variable | name: array_size | {{.*}} | loc: 59:22 -// CHECK: [indexEntityReference]: kind: variable | name: default_param | {{.*}} | loc: 62:19 +// CHECK: [indexEntityReference]: kind: variable | name: default_param | {{.*}} | loc: 62:19 | {{.*}} | role: ref read // CHECK-NOT: [indexEntityReference]: kind: variable | name: default_param | {{.*}} | loc: 62:19 // CHECK: [indexEntityReference]: kind: field | name: y | {{.*}} | loc: 69:20 @@ -125,6 +128,11 @@ // CHECK-NOT: [indexEntityReference]: kind: field | name: y | {{.*}} | loc: 69:20 // CHECK-NOT: [indexEntityReference]: kind: field | name: x | {{.*}} | loc: 69:28 +// CHECK: [indexEntityReference]: kind: field | name: y | {{.*}} | loc: 70:5 | {{.*}} | role: ref write +// CHECK: [indexEntityReference]: kind: field | name: x | {{.*}} | loc: 70:11 | {{.*}} | role: ref read +// CHECK: [indexEntityReference]: kind: function | name: foo3 | {{.*}} | loc: 71:10 | {{.*}} | role: ref addr +// CHECK: [indexEntityReference]: kind: function | name: foo4 | {{.*}} | loc: 72:3 | {{.*}} | role: ref call + // CHECK: [indexDeclaration]: kind: variable | name: ginitlist | -// CHECK: [indexEntityReference]: kind: enumerator | name: EnumVal | {{.*}} | loc: 72:20 -// CHECK-NOT: [indexEntityReference]: kind: enumerator | name: EnumVal | {{.*}} | loc: 72:20 +// CHECK: [indexEntityReference]: kind: enumerator | name: EnumVal | {{.*}} | loc: 75:20 +// CHECK-NOT: [indexEntityReference]: kind: enumerator | name: EnumVal | {{.*}} | loc: 75:20 Index: test/Index/index-subscripting-literals.m =================================================================== --- test/Index/index-subscripting-literals.m +++ test/Index/index-subscripting-literals.m @@ -42,7 +42,7 @@ // RUN: c-index-test -index-file -target x86_64-apple-macosx10.7 %s | FileCheck %s // CHECK: [indexEntityReference]: kind: variable | name: idx | USR: c:@idx | lang: C | cursor: DeclRefExpr=idx:22:5 | loc: 27:9 -// CHECK-NEXT: [indexEntityReference]: kind: variable | name: p | USR: c:@p | lang: C | cursor: DeclRefExpr=p:23:4 | loc: 27:16 | :: kind: function | name: testArray | USR: c:@F@testArray | lang: C | container: [testArray:25:4] | refkind: direct +// CHECK-NEXT: [indexEntityReference]: kind: variable | name: p | USR: c:@p | lang: C | cursor: DeclRefExpr=p:23:4 | loc: 27:16 | :: kind: function | name: testArray | USR: c:@F@testArray | lang: C | container: [testArray:25:4] | refkind: direct | role: ref // CHECK-NEXT: [indexEntityReference]: kind: objc-instance-method | name: setObject:atIndexedSubscript: // CHECK-NEXT: [indexEntityReference]: kind: objc-class | name: NSArray // CHECK-NEXT: [indexEntityReference]: kind: objc-class-method | name: arrayWithObjects:count: Index: tools/c-index-test/c-index-test.c =================================================================== --- tools/c-index-test/c-index-test.c +++ tools/c-index-test/c-index-test.c @@ -3326,6 +3326,27 @@ } } +static void printSymbolRole(CXSymbolRole role) { + if (role & CXSymbolRole_Declaration) + printf(" decl"); + if (role & CXSymbolRole_Definition) + printf(" def"); + if (role & CXSymbolRole_Reference) + printf(" ref"); + if (role & CXSymbolRole_Read) + printf(" read"); + if (role & CXSymbolRole_Write) + printf(" write"); + if (role & CXSymbolRole_Call) + printf(" call"); + if (role & CXSymbolRole_Dynamic) + printf(" dyn"); + if (role & CXSymbolRole_AddressOf) + printf(" addr"); + if (role & CXSymbolRole_Implicit) + printf(" implicit"); +} + static void index_diagnostic(CXClientData client_data, CXDiagnosticSet diagSet, void *reserved) { CXString str; @@ -3544,9 +3565,11 @@ printCXIndexContainer(info->container); printf(" | refkind: "); switch (info->kind) { - case CXIdxEntityRef_Direct: printf("direct"); break; - case CXIdxEntityRef_Implicit: printf("implicit"); break; + case CXIdxEntityRef_Direct: printf("direct"); break; + case CXIdxEntityRef_Implicit: printf("implicit"); break; } + printf(" | role:"); + printSymbolRole(info->role); printf("\n"); } Index: tools/libclang/CXIndexDataConsumer.h =================================================================== --- tools/libclang/CXIndexDataConsumer.h +++ tools/libclang/CXIndexDataConsumer.h @@ -436,13 +436,15 @@ const NamedDecl *Parent, const DeclContext *DC, const Expr *E = nullptr, - CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct); + CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct, + CXSymbolRole Role = CXSymbolRole_None); bool handleReference(const NamedDecl *D, SourceLocation Loc, const NamedDecl *Parent, const DeclContext *DC, const Expr *E = nullptr, - CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct); + CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct, + CXSymbolRole Role = CXSymbolRole_None); bool isNotFromSourceFile(SourceLocation Loc) const; Index: tools/libclang/CXIndexDataConsumer.cpp =================================================================== --- tools/libclang/CXIndexDataConsumer.cpp +++ tools/libclang/CXIndexDataConsumer.cpp @@ -148,6 +148,11 @@ return true; } }; + +CXSymbolRole getSymbolRole(SymbolRoleSet Role) { + // CXSymbolRole mirrors low 9 bits of clang::index::SymbolRole. + return CXSymbolRole(static_cast(Role) & ((1 << 9) - 1)); +} } bool CXIndexDataConsumer::handleDeclOccurence(const Decl *D, @@ -184,6 +189,7 @@ if (Roles & (unsigned)SymbolRole::Implicit) { Kind = CXIdxEntityRef_Implicit; } + CXSymbolRole CXRole = getSymbolRole(Roles); CXCursor Cursor; if (ASTNode.OrigE) { @@ -202,7 +208,7 @@ } handleReference(ND, Loc, Cursor, dyn_cast_or_null(ASTNode.Parent), - ASTNode.ContainerDC, ASTNode.OrigE, Kind); + ASTNode.ContainerDC, ASTNode.OrigE, Kind, CXRole); } else { const DeclContext *LexicalDC = ASTNode.ContainerDC; @@ -889,13 +895,14 @@ const NamedDecl *Parent, const DeclContext *DC, const Expr *E, - CXIdxEntityRefKind Kind) { + CXIdxEntityRefKind Kind, + CXSymbolRole Role) { if (!D || !DC) return false; CXCursor Cursor = E ? MakeCXCursor(E, cast(DC), CXTU) : getRefCursor(D, Loc); - return handleReference(D, Loc, Cursor, Parent, DC, E, Kind); + return handleReference(D, Loc, Cursor, Parent, DC, E, Kind, Role); } bool CXIndexDataConsumer::handleReference(const NamedDecl *D, SourceLocation Loc, @@ -903,7 +910,8 @@ const NamedDecl *Parent, const DeclContext *DC, const Expr *E, - CXIdxEntityRefKind Kind) { + CXIdxEntityRefKind Kind, + CXSymbolRole Role) { if (!CB.indexEntityReference) return false; @@ -939,7 +947,8 @@ getIndexLoc(Loc), &RefEntity, Parent ? &ParentEntity : nullptr, - &Container }; + &Container, + Role }; CB.indexEntityReference(ClientData, &Info); return true; }