From: Douglas Gregor Date: Tue, 19 Jan 2010 01:20:04 +0000 (+0000) Subject: Introduce clang_getCursorReferenced, to get a cursor pointing at the X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c5d1e9375d71e66d22456e7cc52cc7c0a5c65c3f;p=clang Introduce clang_getCursorReferenced, to get a cursor pointing at the entity that a particular cursor references. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@93830 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index 50ce14a15a..7b7c53ebaf 100644 --- a/include/clang-c/Index.h +++ b/include/clang-c/Index.h @@ -334,10 +334,10 @@ CINDEX_LINKAGE CXDecl clang_getDeclaration(CXEntity, CXTranslationUnit); CINDEX_LINKAGE CXCursor clang_getCursorFromDecl(CXDecl); CINDEX_LINKAGE CXEntity clang_getEntityFromDecl(CXIndex, CXDecl); CINDEX_LINKAGE CXString clang_getDeclSpelling(CXDecl); -CINDEX_LINKAGE unsigned clang_getDeclLine(CXDecl); -CINDEX_LINKAGE unsigned clang_getDeclColumn(CXDecl); +CINDEX_LINKAGE unsigned clang_getDeclLine(CXDecl); /* deprecate */ +CINDEX_LINKAGE unsigned clang_getDeclColumn(CXDecl); /* deprecate */ CINDEX_LINKAGE const char *clang_getDeclSource(CXDecl); /* deprecate */ -CINDEX_LINKAGE CXFile clang_getDeclSourceFile(CXDecl); +CINDEX_LINKAGE CXFile clang_getDeclSourceFile(CXDecl); /* deprecate */ /** * \brief Identifies a specific source location given its file, line, and @@ -418,6 +418,18 @@ CINDEX_LINKAGE CXSourceLocation clang_getCursorLocation(CXCursor); * entity was actually used). */ CINDEX_LINKAGE CXSourceRange clang_getCursorExtent(CXCursor); + +/** \brief For a cursor that is a reference, retrieve a cursor representing the + * entity that it references. + * + * Reference cursors refer to other entities in the AST. For example, an + * Objective-C superclass reference cursor refers to an Objective-C class. + * This function produces the cursor for the Objective-C class from the + * cursor for the superclass reference. If the input cursor is a declaration or + * definition, it returns that declaration or definition unchanged. + * Othewise, returns the NULL cursor. + */ +CINDEX_LINKAGE CXCursor clang_getCursorReferenced(CXCursor); /* for debug/testing */ CINDEX_LINKAGE const char *clang_getCursorKindSpelling(enum CXCursorKind Kind); diff --git a/test/Index/TestClassDecl.m b/test/Index/TestClassDecl.m index 20431ca23f..a536b99644 100644 --- a/test/Index/TestClassDecl.m +++ b/test/Index/TestClassDecl.m @@ -32,7 +32,7 @@ void function(Foo * arg) // CHECK-scan: {start_line=13 start_col=24 end_line=16 end_col=1} FunctionDefn=function:13:6 // CHECK-scan: {start_line=16 start_col=2 end_line=38 end_col=1} Invalid Cursor => NoDeclFound -// CHECK-load: TestClassDecl.m:10:12: ObjCInterfaceDecl=Foo:10:1 [Extent=10:1:11:4] +// CHECK-load: TestClassDecl.m:10:12: ObjCInterfaceDecl=Foo:10:12 [Extent=10:1:11:4] // CHECK-load: TestClassDecl.m:13:6: FunctionDefn=function:13:6 [Extent=13:6:16:1] // CHECK-load: TestClassDecl.m:13:21: ParmDecl=arg:13:21 [Extent=13:21:13:23] diff --git a/test/Index/TestClassForwardDecl.m b/test/Index/TestClassForwardDecl.m index c9d9831d51..2f08ce9869 100644 --- a/test/Index/TestClassForwardDecl.m +++ b/test/Index/TestClassForwardDecl.m @@ -14,12 +14,12 @@ void function(Foo * arg) // CHECK-scan: {start_line=1 start_col=1 end_line=7 end_col=1} Invalid Cursor => NoDeclFound // CHECK-scan: {start_line=8 start_col=1 end_line=8 end_col=7} Invalid Cursor => NotImplemented -// CHECK-scan: {start_line=8 start_col=8 end_line=8 end_col=10} ObjCClassRef=Foo:8:1 +// CHECK-scan: {start_line=8 start_col=8 end_line=8 end_col=10} ObjCClassRef=Foo:8:8 // CHECK-scan: {start_line=8 start_col=11 end_line=9 end_col=1} Invalid Cursor => NoDeclFound // CHECK-scan: {start_line=10 start_col=1 end_line=10 end_col=4} FunctionDefn=function:10:6 // CHECK-scan: {start_line=10 start_col=5 end_line=10 end_col=5} Invalid Cursor => NoDeclFound // CHECK-scan: {start_line=10 start_col=6 end_line=10 end_col=14} FunctionDefn=function:10:6 -// CHECK-scan: {start_line=10 start_col=15 end_line=10 end_col=17} ObjCClassRef=Foo:8:1 +// CHECK-scan: {start_line=10 start_col=15 end_line=10 end_col=17} ObjCClassRef=Foo:8:8 // CHECK-scan: {start_line=10 start_col=18 end_line=10 end_col=18} FunctionDefn=function:10:6 // CHECK-scan: {start_line=10 start_col=19 end_line=10 end_col=19} ParmDecl=arg:10:21 // CHECK-scan: {start_line=10 start_col=20 end_line=10 end_col=20} FunctionDefn=function:10:6 diff --git a/test/Index/c-index-api-loadTU-test.m b/test/Index/c-index-api-loadTU-test.m index db7f09866f..836f335c9a 100644 --- a/test/Index/c-index-api-loadTU-test.m +++ b/test/Index/c-index-api-loadTU-test.m @@ -53,13 +53,13 @@ int main (int argc, const char * argv[]) { main(someEnum, (const char **)bee); } -// CHECK: c-index-api-loadTU-test.m:4:12: ObjCInterfaceDecl=Foo:4:1 [Extent=4:1:11:4] +// CHECK: c-index-api-loadTU-test.m:4:12: ObjCInterfaceDecl=Foo:4:12 [Extent=4:1:11:4] // CHECK: c-index-api-loadTU-test.m:8:1: ObjCInstanceMethodDecl=foo:8:1 [Extent=8:1:8:6] // CHECK: c-index-api-loadTU-test.m:9:1: ObjCClassMethodDecl=fooC:9:1 [Extent=9:1:9:7] -// CHECK: c-index-api-loadTU-test.m:13:12: ObjCInterfaceDecl=Bar:13:1 [Extent=13:1:17:4] -// CHECK: c-index-api-loadTU-test.m:13:18: ObjCSuperClassRef=Foo:4:1 [Extent=13:18:13:20] +// CHECK: c-index-api-loadTU-test.m:13:12: ObjCInterfaceDecl=Bar:13:12 [Extent=13:1:17:4] +// CHECK: c-index-api-loadTU-test.m:13:18: ObjCSuperClassRef=Foo:4:12 [Extent=13:18:13:20] // CHECK: c-index-api-loadTU-test.m:19:12: ObjCCategoryDecl=FooCat:19:12 [Extent=19:1:22:4] -// CHECK: c-index-api-loadTU-test.m:19:12: ObjCClassRef=Foo:4:1 [Extent=19:12:19:14] +// CHECK: c-index-api-loadTU-test.m:19:12: ObjCClassRef=Foo:4:12 [Extent=19:12:19:14] // CHECK: c-index-api-loadTU-test.m:20:1: ObjCInstanceMethodDecl=catMethodWithFloat::20:1 [Extent=20:1:20:40] // CHECK: c-index-api-loadTU-test.m:21:1: ObjCInstanceMethodDecl=floatMethod:21:1 [Extent=21:1:21:22] // CHECK: c-index-api-loadTU-test.m:24:1: ObjCProtocolDecl=Proto:24:1 [Extent=24:1:26:4] @@ -67,8 +67,8 @@ int main (int argc, const char * argv[]) { // CHECK: c-index-api-loadTU-test.m:28:1: ObjCProtocolDecl=SubP:28:1 [Extent=28:1:30:4] // CHECK: c-index-api-loadTU-test.m:28:17: ObjCProtocolRef=Proto:24:1 [Extent=28:17:28:21] // CHECK: c-index-api-loadTU-test.m:29:1: ObjCInstanceMethodDecl=spMethod:29:1 [Extent=29:1:29:11] -// CHECK: c-index-api-loadTU-test.m:32:12: ObjCInterfaceDecl=Baz:32:1 [Extent=32:1:39:4] -// CHECK: c-index-api-loadTU-test.m:32:18: ObjCSuperClassRef=Bar:13:1 [Extent=32:18:32:20] +// CHECK: c-index-api-loadTU-test.m:32:12: ObjCInterfaceDecl=Baz:32:12 [Extent=32:1:39:4] +// CHECK: c-index-api-loadTU-test.m:32:18: ObjCSuperClassRef=Bar:13:12 [Extent=32:18:32:20] // CHECK: c-index-api-loadTU-test.m:32:23: ObjCProtocolRef=SubP:28:1 [Extent=32:23:32:26] // CHECK: c-index-api-loadTU-test.m:34:9: ObjCIvarDecl=_anIVar:34:9 [Extent=34:9:34:15] // CHECK: c-index-api-loadTU-test.m:37:1: ObjCInstanceMethodDecl=bazMethod:37:1 [Extent=37:1:37:20] diff --git a/tools/CIndex/CIndex.cpp b/tools/CIndex/CIndex.cpp index 9e7408375f..355b80dfd8 100644 --- a/tools/CIndex/CIndex.cpp +++ b/tools/CIndex/CIndex.cpp @@ -1006,7 +1006,46 @@ CXSourceRange clang_getCursorExtent(CXCursor C) { Decl *D = getCursorDecl(C); return translateSourceRange(D->getASTContext(), D->getSourceRange()); } + +CXCursor clang_getCursorReferenced(CXCursor C) { + if (clang_isDeclaration(C.kind) || clang_isDefinition(C.kind)) + return C; + + if (!clang_isReference(C.kind)) + return clang_getNullCursor(); + + switch (C.kind) { + case CXCursor_ObjCSuperClassRef: + return MakeCXCursor(getCursorObjCSuperClassRef(C).first); + + case CXCursor_ObjCProtocolRef: { + return MakeCXCursor(getCursorObjCProtocolRef(C).first); + + case CXCursor_ObjCClassRef: + return MakeCXCursor(getCursorObjCClassRef(C).first); + + case CXCursor_ObjCSelectorRef: + case CXCursor_ObjCIvarRef: + case CXCursor_VarRef: + case CXCursor_FunctionRef: + case CXCursor_EnumConstantRef: + case CXCursor_MemberRef: { + Decl *D = getDeclFromExpr(getCursorExpr(C)); + if (D) + return MakeCXCursor(D); + break; + } + + default: + // We would prefer to enumerate all non-reference cursor kinds here. + llvm_unreachable("Unhandled reference cursor kind"); + break; + } + } + return clang_getNullCursor(); +} + void clang_getDefinitionSpellingAndExtent(CXCursor C, const char **startBuf, const char **endBuf, diff --git a/tools/CIndex/CIndex.exports b/tools/CIndex/CIndex.exports index 0272f37e50..71522fd3ed 100644 --- a/tools/CIndex/CIndex.exports +++ b/tools/CIndex/CIndex.exports @@ -18,6 +18,7 @@ _clang_getCursorFromDecl _clang_getCursorKind _clang_getCursorKindSpelling _clang_getCursorLocation +_clang_getCursorReferenced _clang_getCursorSpelling _clang_getCursorUSR _clang_getDeclColumn diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c index 2f113cfada..34332d3e40 100644 --- a/tools/c-index-test/c-index-test.c +++ b/tools/c-index-test/c-index-test.c @@ -47,16 +47,18 @@ static void PrintCursor(CXCursor Cursor) { if (clang_isInvalid(Cursor.kind)) printf("Invalid Cursor => %s", clang_getCursorKindSpelling(Cursor.kind)); else { - CXDecl DeclReferenced; CXString string; + CXCursor Referenced; string = clang_getCursorSpelling(Cursor); printf("%s=%s", clang_getCursorKindSpelling(Cursor.kind), clang_getCString(string)); clang_disposeString(string); - DeclReferenced = clang_getCursorDecl(Cursor); - if (DeclReferenced) - printf(":%d:%d", clang_getDeclLine(DeclReferenced), - clang_getDeclColumn(DeclReferenced)); + + Referenced = clang_getCursorReferenced(Cursor); + if (!clang_equalCursors(Referenced, clang_getNullCursor())) { + CXSourceLocation Loc = clang_getCursorLocation(Referenced); + printf(":%d:%d", Loc.line, Loc.column); + } } }