From: Douglas Gregor Date: Tue, 19 Jan 2010 19:34:47 +0000 (+0000) Subject: Eliminate cursor kinds used to express definitions. Instead, provide X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b699866820102a69d83d6ac6941985c5ef4e8c40;p=clang Eliminate cursor kinds used to express definitions. Instead, provide CIndex functions that (1) map from a reference or declaration to the corresponding definition, if available, and (2) determine whether a given declaration cursor is also a definition. This eliminates a lot of duplication in the cursor kinds, and maps more closely to the Clang ASTs. This is another API + ABI breaker with no deprecation. Yay, progress. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@93893 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index 7b7c53ebaf..0cf2d2b785 100644 --- a/include/clang-c/Index.h +++ b/include/clang-c/Index.h @@ -72,17 +72,10 @@ enum CXCursorKind { CXCursor_ObjCIvarDecl = 15, CXCursor_ObjCInstanceMethodDecl = 16, CXCursor_ObjCClassMethodDecl = 17, - CXCursor_LastDecl = 17, + CXCursor_ObjCImplementationDecl = 18, + CXCursor_ObjCCategoryImplDecl = 19, + CXCursor_LastDecl = 19, - /* Definitions */ - CXCursor_FirstDefn = 32, - CXCursor_FunctionDefn = 32, - CXCursor_ObjCClassDefn = 33, - CXCursor_ObjCCategoryDefn = 34, - CXCursor_ObjCInstanceMethodDefn = 35, - CXCursor_ObjCClassMethodDefn = 36, - CXCursor_LastDefn = 36, - /* References */ CXCursor_FirstRef = 40, /* Decl references */ CXCursor_ObjCSuperClassRef = 40, @@ -388,7 +381,6 @@ CINDEX_LINKAGE CXString clang_getCursorUSR(CXCursor); CINDEX_LINKAGE enum CXCursorKind clang_getCursorKind(CXCursor); CINDEX_LINKAGE unsigned clang_isDeclaration(enum CXCursorKind); CINDEX_LINKAGE unsigned clang_isReference(enum CXCursorKind); -CINDEX_LINKAGE unsigned clang_isDefinition(enum CXCursorKind); CINDEX_LINKAGE unsigned clang_isInvalid(enum CXCursorKind); CINDEX_LINKAGE unsigned clang_equalCursors(CXCursor, CXCursor); @@ -407,7 +399,8 @@ CINDEX_LINKAGE CXString clang_getCursorSpelling(CXCursor); */ CINDEX_LINKAGE CXSourceLocation clang_getCursorLocation(CXCursor); -/** \brief Retrieve the physical extent of the source construct referenced by +/** + * \brief Retrieve the physical extent of the source construct referenced by * the given cursor. * * The extent of a cursor starts with the file/line/column pointing at the @@ -430,7 +423,43 @@ CINDEX_LINKAGE CXSourceRange clang_getCursorExtent(CXCursor); * Othewise, returns the NULL cursor. */ CINDEX_LINKAGE CXCursor clang_getCursorReferenced(CXCursor); - + +/** + * \brief For a cursor that is either a reference to or a declaration + * of some entity, retrieve a cursor that describes the definition of + * that entity. + * + * Some entities can be declared multiple times within a translation + * unit, but only one of those declarations can also be a + * definition. For example, given: + * + * \code + * int f(int, int); + * int g(int x, int y) { return f(x, y); } + * int f(int a, int b) { return a + b; } + * int f(int, int); + * \endcode + * + * there are three declarations of the function "f", but only the + * second one is a definition. The clang_getCursorDefinition() + * function will take any cursor pointing to a declaration of "f" + * (the first or fourth lines of the example) or a cursor referenced + * that uses "f" (the call to "f' inside "g") and will return a + * declaration cursor pointing to the definition (the second "f" + * declaration). + * + * If given a cursor for which there is no corresponding definition, + * e.g., because there is no definition of that entity within this + * translation unit, returns a NULL cursor. + */ +CINDEX_LINKAGE CXCursor clang_getCursorDefinition(CXCursor); + +/** + * \brief Determine whether the declaration pointed to by this cursor + * is also a definition of that entity. + */ +CINDEX_LINKAGE unsigned clang_isCursorDefinition(CXCursor); + /* for debug/testing */ CINDEX_LINKAGE const char *clang_getCursorKindSpelling(enum CXCursorKind Kind); CINDEX_LINKAGE void clang_getDefinitionSpellingAndExtent(CXCursor, diff --git a/lib/Sema/CodeCompleteConsumer.cpp b/lib/Sema/CodeCompleteConsumer.cpp index fbd14502b7..8c4caafeac 100644 --- a/lib/Sema/CodeCompleteConsumer.cpp +++ b/lib/Sema/CodeCompleteConsumer.cpp @@ -572,11 +572,11 @@ CIndexCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef, break; case Decl::ObjCImplementation: - Kind = CXCursor_ObjCClassDefn; + Kind = CXCursor_ObjCImplementationDecl; break; case Decl::ObjCCategoryImpl: - Kind = CXCursor_ObjCCategoryDefn; + Kind = CXCursor_ObjCCategoryImplDecl; break; default: diff --git a/test/Index/TestClassDecl.m b/test/Index/TestClassDecl.m index a536b99644..8bbe949948 100644 --- a/test/Index/TestClassDecl.m +++ b/test/Index/TestClassDecl.m @@ -21,18 +21,18 @@ void function(Foo * arg) // 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=11 end_col=4} ObjCInterfaceDecl=Foo:10:1 // CHECK-scan: {start_line=11 start_col=5 end_line=12 end_col=1} Invalid Cursor => NoDeclFound -// CHECK-scan: {start_line=13 start_col=1 end_line=13 end_col=4} FunctionDefn=function:13:6 +// CHECK-scan: {start_line=13 start_col=1 end_line=13 end_col=4} FunctionDecl=function:13:6 (Definition) // CHECK-scan: {start_line=13 start_col=5 end_line=13 end_col=5} Invalid Cursor => NoDeclFound -// CHECK-scan: {start_line=13 start_col=6 end_line=13 end_col=14} FunctionDefn=function:13:6 +// CHECK-scan: {start_line=13 start_col=6 end_line=13 end_col=14} FunctionDecl=function:13:6 (Definition) // CHECK-scan: {start_line=13 start_col=15 end_line=13 end_col=17} ObjCClassRef=Foo:10:1 -// CHECK-scan: {start_line=13 start_col=18 end_line=13 end_col=18} FunctionDefn=function:13:6 +// CHECK-scan: {start_line=13 start_col=18 end_line=13 end_col=18} FunctionDecl=function:13:6 (Definition) // CHECK-scan: {start_line=13 start_col=19 end_line=13 end_col=19} ParmDecl=arg:13:21 -// CHECK-scan: {start_line=13 start_col=20 end_line=13 end_col=20} FunctionDefn=function:13:6 +// CHECK-scan: {start_line=13 start_col=20 end_line=13 end_col=20} FunctionDecl=function:13:6 (Definition) // CHECK-scan: {start_line=13 start_col=21 end_line=13 end_col=23} ParmDecl=arg:13:21 -// CHECK-scan: {start_line=13 start_col=24 end_line=16 end_col=1} FunctionDefn=function:13:6 +// CHECK-scan: {start_line=13 start_col=24 end_line=16 end_col=1} FunctionDecl=function:13:6 (Definition) // 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: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] +// CHECK-load: TestClassDecl.m:13:6: FunctionDecl=function:13:6 (Definition) [Extent=13:6:16:1] +// CHECK-load: TestClassDecl.m:13:21: ParmDecl=arg:13:21 (Definition) [Extent=13:21:13:23] diff --git a/test/Index/TestClassForwardDecl.m b/test/Index/TestClassForwardDecl.m index 2f08ce9869..65b7c6f515 100644 --- a/test/Index/TestClassForwardDecl.m +++ b/test/Index/TestClassForwardDecl.m @@ -16,15 +16,15 @@ void function(Foo * arg) // 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: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=1 end_line=10 end_col=4} FunctionDecl=function:10:6 (Definition) // 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=6 end_line=10 end_col=14} FunctionDecl=function:10:6 (Definition) // 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=18 end_line=10 end_col=18} FunctionDecl=function:10:6 (Definition) // 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 +// CHECK-scan: {start_line=10 start_col=20 end_line=10 end_col=20} FunctionDecl=function:10:6 (Definition) // CHECK-scan: {start_line=10 start_col=21 end_line=10 end_col=23} ParmDecl=arg:10:21 -// CHECK-scan: {start_line=10 start_col=24 end_line=13 end_col=1} FunctionDefn=function:10:6 +// CHECK-scan: {start_line=10 start_col=24 end_line=13 end_col=1} FunctionDecl=function:10:6 (Definition) // CHECK-scan: {start_line=13 start_col=2 end_line=46 end_col=1} Invalid Cursor => NoDeclFound @@ -41,6 +41,6 @@ void function(Foo * arg) -// CHECK-load: TestClassForwardDecl.m:10:6: FunctionDefn=function:10:6 +// CHECK-load: TestClassForwardDecl.m:10:6: FunctionDecl=function:10:6 (Definition) // CHECK-load: TestClassForwardDecl.m:10:21: ParmDecl=arg:10:21 diff --git a/test/Index/c-index-api-loadTU-test.m b/test/Index/c-index-api-loadTU-test.m index 836f335c9a..349f52139c 100644 --- a/test/Index/c-index-api-loadTU-test.m +++ b/test/Index/c-index-api-loadTU-test.m @@ -62,24 +62,24 @@ int main (int argc, const char * argv[]) { // 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] +// CHECK: c-index-api-loadTU-test.m:24:1: ObjCProtocolDecl=Proto:24:1 (Definition) [Extent=24:1:26:4] // CHECK: c-index-api-loadTU-test.m:25:1: ObjCInstanceMethodDecl=pMethod:25:1 [Extent=25:1:25:10] -// 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:1: ObjCProtocolDecl=SubP:28:1 (Definition) [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: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:34:9: ObjCIvarDecl=_anIVar:34:9 (Definition) [Extent=34:9:34:15] // CHECK: c-index-api-loadTU-test.m:37:1: ObjCInstanceMethodDecl=bazMethod:37:1 [Extent=37:1:37:20] -// CHECK: c-index-api-loadTU-test.m:41:1: EnumDecl=:41:1 [Extent=41:1:43:1] -// CHECK: c-index-api-loadTU-test.m:42:3: EnumConstantDecl=someEnum:42:3 [Extent=42:3:42:10] -// CHECK: c-index-api-loadTU-test.m:45:5: FunctionDefn=main:45:5 [Extent=45:5:54:1] -// CHECK: c-index-api-loadTU-test.m:45:15: ParmDecl=argc:45:15 [Extent=45:15:45:18] -// CHECK: c-index-api-loadTU-test.m:45:34: ParmDecl=argv:45:34 [Extent=45:34:45:37] -// CHECK: c-index-api-loadTU-test.m:46:8: VarDecl=bee:46:8 [Extent=46:8:46:10] -// CHECK: c-index-api-loadTU-test.m:47:5: VarDecl=a:47:5 [Extent=47:5:47:17] -// CHECK: c-index-api-loadTU-test.m:48:12: VarDecl=c:48:12 [Extent=48:12:48:25] -// CHECK: c-index-api-loadTU-test.m:49:13: VarDecl=d:49:13 [Extent=49:13:49:13] +// CHECK: c-index-api-loadTU-test.m:41:1: EnumDecl=:41:1 (Definition) [Extent=41:1:43:1] +// CHECK: c-index-api-loadTU-test.m:42:3: EnumConstantDecl=someEnum:42:3 (Definition) [Extent=42:3:42:10] +// CHECK: c-index-api-loadTU-test.m:45:5: FunctionDecl=main:45:5 (Definition) [Extent=45:5:54:1] +// CHECK: c-index-api-loadTU-test.m:45:15: ParmDecl=argc:45:15 (Definition) [Extent=45:15:45:18] +// CHECK: c-index-api-loadTU-test.m:45:34: ParmDecl=argv:45:34 (Definition) [Extent=45:34:45:37] +// CHECK: c-index-api-loadTU-test.m:46:8: VarDecl=bee:46:8 (Definition) [Extent=46:8:46:10] +// CHECK: c-index-api-loadTU-test.m:47:5: VarDecl=a:47:5 (Definition) [Extent=47:5:47:17] +// CHECK: c-index-api-loadTU-test.m:48:12: VarDecl=c:48:12 (Definition) [Extent=48:12:48:25] +// CHECK: c-index-api-loadTU-test.m:49:13: VarDecl=d:49:13 (Definition) [Extent=49:13:49:13] diff --git a/test/Index/c-index-getCursor-test.m b/test/Index/c-index-getCursor-test.m index 7ea996f76c..8e2f37f134 100644 --- a/test/Index/c-index-getCursor-test.m +++ b/test/Index/c-index-getCursor-test.m @@ -91,57 +91,57 @@ int main (int argc, const char * argv[]) { // CHECK: {start_line=41 start_col=3 end_line=41 end_col=10} EnumConstantDecl=someEnum:41:3 // CHECK: {start_line=41 start_col=11 end_line=42 end_col=1} EnumDecl=:40:1 // CHECK: {start_line=42 start_col=2 end_line=43 end_col=1} Invalid Cursor => NoDeclFound -// CHECK: {start_line=44 start_col=1 end_line=44 end_col=3} FunctionDefn=main:44:5 +// CHECK: {start_line=44 start_col=1 end_line=44 end_col=3} FunctionDecl=main:44:5 (Definition) // CHECK: {start_line=44 start_col=4 end_line=44 end_col=4} Invalid Cursor => NoDeclFound -// CHECK: {start_line=44 start_col=5 end_line=44 end_col=10} FunctionDefn=main:44:5 +// CHECK: {start_line=44 start_col=5 end_line=44 end_col=10} FunctionDecl=main:44:5 (Definition) // CHECK: {start_line=44 start_col=11 end_line=44 end_col=13} ParmDecl=argc:44:15 -// CHECK: {start_line=44 start_col=14 end_line=44 end_col=14} FunctionDefn=main:44:5 +// CHECK: {start_line=44 start_col=14 end_line=44 end_col=14} FunctionDecl=main:44:5 (Definition) // CHECK: {start_line=44 start_col=15 end_line=44 end_col=18} ParmDecl=argc:44:15 -// CHECK: {start_line=44 start_col=19 end_line=44 end_col=26} FunctionDefn=main:44:5 +// CHECK: {start_line=44 start_col=19 end_line=44 end_col=26} FunctionDecl=main:44:5 (Definition) // CHECK: {start_line=44 start_col=27 end_line=44 end_col=30} ParmDecl=argv:44:34 -// CHECK: {start_line=44 start_col=31 end_line=44 end_col=31} FunctionDefn=main:44:5 +// CHECK: {start_line=44 start_col=31 end_line=44 end_col=31} FunctionDecl=main:44:5 (Definition) // CHECK: {start_line=44 start_col=32 end_line=44 end_col=32} ParmDecl=argv:44:34 -// CHECK: {start_line=44 start_col=33 end_line=44 end_col=33} FunctionDefn=main:44:5 +// CHECK: {start_line=44 start_col=33 end_line=44 end_col=33} FunctionDecl=main:44:5 (Definition) // CHECK: {start_line=44 start_col=34 end_line=44 end_col=39} ParmDecl=argv:44:34 -// CHECK: {start_line=44 start_col=40 end_line=45 end_col=1} FunctionDefn=main:44:5 +// CHECK: {start_line=44 start_col=40 end_line=45 end_col=1} FunctionDecl=main:44:5 (Definition) // CHECK: {start_line=45 start_col=2 end_line=45 end_col=4} ObjCClassRef=Baz:31:1 -// CHECK: {start_line=45 start_col=5 end_line=45 end_col=5} FunctionDefn=main:44:5 +// CHECK: {start_line=45 start_col=5 end_line=45 end_col=5} FunctionDecl=main:44:5 (Definition) // CHECK: {start_line=45 start_col=6 end_line=45 end_col=6} VarDecl=bee:45:8 -// CHECK: {start_line=45 start_col=7 end_line=45 end_col=7} FunctionDefn=main:44:5 +// CHECK: {start_line=45 start_col=7 end_line=45 end_col=7} FunctionDecl=main:44:5 (Definition) // CHECK: {start_line=45 start_col=8 end_line=45 end_col=10} VarDecl=bee:45:8 -// CHECK: {start_line=45 start_col=11 end_line=46 end_col=1} FunctionDefn=main:44:5 +// CHECK: {start_line=45 start_col=11 end_line=46 end_col=1} FunctionDecl=main:44:5 (Definition) // CHECK: {start_line=46 start_col=2 end_line=46 end_col=3} TypedefDecl=id:0:0 -// CHECK: {start_line=46 start_col=4 end_line=46 end_col=4} FunctionDefn=main:44:5 +// CHECK: {start_line=46 start_col=4 end_line=46 end_col=4} FunctionDecl=main:44:5 (Definition) // CHECK: {start_line=46 start_col=5 end_line=46 end_col=8} VarDecl=a:46:5 // CHECK: {start_line=46 start_col=9 end_line=46 end_col=9} ObjCSelectorRef=foo:7:1 // CHECK: {start_line=46 start_col=10 end_line=46 end_col=12} VarRef=bee:45:8 // CHECK: {start_line=46 start_col=13 end_line=46 end_col=17} ObjCSelectorRef=foo:7:1 -// CHECK: {start_line=46 start_col=18 end_line=47 end_col=1} FunctionDefn=main:44:5 +// CHECK: {start_line=46 start_col=18 end_line=47 end_col=1} FunctionDecl=main:44:5 (Definition) // CHECK: {start_line=47 start_col=2 end_line=47 end_col=3} TypedefDecl=id:0:0 -// CHECK: {start_line=47 start_col=4 end_line=47 end_col=4} FunctionDefn=main:44:5 +// CHECK: {start_line=47 start_col=4 end_line=47 end_col=4} FunctionDecl=main:44:5 (Definition) // CHECK: {start_line=47 start_col=5 end_line=47 end_col=5} VarDecl=c:47:12 // CHECK: {start_line=47 start_col=6 end_line=47 end_col=9} ObjCProtocolRef=SubP:27:1 // CHECK: {start_line=47 start_col=10 end_line=47 end_col=10} VarDecl=c:47:12 -// CHECK: {start_line=47 start_col=11 end_line=47 end_col=11} FunctionDefn=main:44:5 +// CHECK: {start_line=47 start_col=11 end_line=47 end_col=11} FunctionDecl=main:44:5 (Definition) // CHECK: {start_line=47 start_col=12 end_line=47 end_col=15} VarDecl=c:47:12 // CHECK: {start_line=47 start_col=16 end_line=47 end_col=25} ObjCSelectorRef=fooC:8:1 -// CHECK: {start_line=47 start_col=26 end_line=48 end_col=1} FunctionDefn=main:44:5 +// CHECK: {start_line=47 start_col=26 end_line=48 end_col=1} FunctionDecl=main:44:5 (Definition) // CHECK: {start_line=48 start_col=2 end_line=48 end_col=3} TypedefDecl=id:0:0 -// CHECK: {start_line=48 start_col=4 end_line=48 end_col=4} FunctionDefn=main:44:5 +// CHECK: {start_line=48 start_col=4 end_line=48 end_col=4} FunctionDecl=main:44:5 (Definition) // CHECK: {start_line=48 start_col=5 end_line=48 end_col=5} VarDecl=d:48:13 // CHECK: {start_line=48 start_col=6 end_line=48 end_col=10} ObjCProtocolRef=Proto:23:1 // CHECK: {start_line=48 start_col=11 end_line=48 end_col=11} VarDecl=d:48:13 -// CHECK: {start_line=48 start_col=12 end_line=48 end_col=12} FunctionDefn=main:44:5 +// CHECK: {start_line=48 start_col=12 end_line=48 end_col=12} FunctionDecl=main:44:5 (Definition) // CHECK: {start_line=48 start_col=13 end_line=48 end_col=13} VarDecl=d:48:13 -// CHECK: {start_line=48 start_col=14 end_line=49 end_col=1} FunctionDefn=main:44:5 +// CHECK: {start_line=48 start_col=14 end_line=49 end_col=1} FunctionDecl=main:44:5 (Definition) // CHECK: {start_line=49 start_col=2 end_line=49 end_col=2} VarRef=d:48:13 -// CHECK: {start_line=49 start_col=3 end_line=49 end_col=5} FunctionDefn=main:44:5 +// CHECK: {start_line=49 start_col=3 end_line=49 end_col=5} FunctionDecl=main:44:5 (Definition) // CHECK: {start_line=49 start_col=6 end_line=49 end_col=6} VarRef=c:47:12 -// CHECK: {start_line=49 start_col=7 end_line=50 end_col=1} FunctionDefn=main:44:5 +// CHECK: {start_line=49 start_col=7 end_line=50 end_col=1} FunctionDecl=main:44:5 (Definition) // CHECK: {start_line=50 start_col=2 end_line=50 end_col=2} ObjCSelectorRef=pMethod:24:1 // CHECK: {start_line=50 start_col=3 end_line=50 end_col=3} VarRef=d:48:13 // CHECK: {start_line=50 start_col=4 end_line=50 end_col=12} ObjCSelectorRef=pMethod:24:1 -// CHECK: {start_line=50 start_col=13 end_line=51 end_col=1} FunctionDefn=main:44:5 +// CHECK: {start_line=50 start_col=13 end_line=51 end_col=1} FunctionDecl=main:44:5 (Definition) // CHECK: {start_line=51 start_col=2 end_line=51 end_col=2} ObjCSelectorRef=catMethodWithFloat::19:1 // CHECK: {start_line=51 start_col=3 end_line=51 end_col=5} VarRef=bee:45:8 // CHECK: {start_line=51 start_col=6 end_line=51 end_col=25} ObjCSelectorRef=catMethodWithFloat::19:1 @@ -149,12 +149,12 @@ int main (int argc, const char * argv[]) { // CHECK: {start_line=51 start_col=27 end_line=51 end_col=29} VarRef=bee:45:8 // CHECK: {start_line=51 start_col=30 end_line=51 end_col=42} ObjCSelectorRef=floatMethod:20:1 // CHECK: {start_line=51 start_col=43 end_line=51 end_col=43} ObjCSelectorRef=catMethodWithFloat::19:1 -// CHECK: {start_line=51 start_col=44 end_line=52 end_col=2} FunctionDefn=main:44:5 +// CHECK: {start_line=51 start_col=44 end_line=52 end_col=2} FunctionDecl=main:44:5 (Definition) // CHECK: {start_line=52 start_col=3 end_line=52 end_col=6} FunctionRef=main:44:5 -// CHECK: {start_line=52 start_col=7 end_line=52 end_col=7} FunctionDefn=main:44:5 +// CHECK: {start_line=52 start_col=7 end_line=52 end_col=7} FunctionDecl=main:44:5 (Definition) // CHECK: {start_line=52 start_col=8 end_line=52 end_col=15} EnumConstantRef=someEnum:41:3 -// CHECK: {start_line=52 start_col=16 end_line=52 end_col=32} FunctionDefn=main:44:5 +// CHECK: {start_line=52 start_col=16 end_line=52 end_col=32} FunctionDecl=main:44:5 (Definition) // CHECK: {start_line=52 start_col=33 end_line=52 end_col=35} VarRef=bee:45:8 -// CHECK: {start_line=52 start_col=36 end_line=53 end_col=1} FunctionDefn=main:44:5 +// CHECK: {start_line=52 start_col=36 end_line=53 end_col=1} FunctionDecl=main:44:5 (Definition) // CHECK: {start_line=53 start_col=2 end_line=160 end_col=1} Invalid Cursor => NoDeclFound diff --git a/test/Index/resolve-loc.c b/test/Index/resolve-loc.c index cbc371a76c..8c2a97a447 100644 --- a/test/Index/resolve-loc.c +++ b/test/Index/resolve-loc.c @@ -24,7 +24,7 @@ struct S { // CHECK: VarDecl=top_var // CHECK: FunctionDecl=top_func_decl // CHECK: ParmDecl=param1 -// CHECK: FunctionDefn=top_func_def +// CHECK: FunctionDecl=top_func_def:7:6 (Definition) // CHECK: ParmDecl=param2 // CHECK: VarDecl=local_var1 // CHECK: VarDecl=for_var diff --git a/tools/CIndex/CIndex.cpp b/tools/CIndex/CIndex.cpp index 355b80dfd8..e6b4bafc33 100644 --- a/tools/CIndex/CIndex.cpp +++ b/tools/CIndex/CIndex.cpp @@ -365,13 +365,11 @@ void CDeclVisitor::VisitObjCIvarDecl(ObjCIvarDecl *ND) { } void CDeclVisitor::VisitObjCMethodDecl(ObjCMethodDecl *ND) { - if (ND->getBody()) { - Call(ND->isInstanceMethod() ? CXCursor_ObjCInstanceMethodDefn - : CXCursor_ObjCClassMethodDefn, ND); + Call(ND->isInstanceMethod() ? CXCursor_ObjCInstanceMethodDecl + : CXCursor_ObjCClassMethodDecl, ND); + + if (ND->getBody()) VisitDeclContext(dyn_cast(ND)); - } else - Call(ND->isInstanceMethod() ? CXCursor_ObjCInstanceMethodDecl - : CXCursor_ObjCClassMethodDecl, ND); } void CDeclVisitor::VisitObjCPropertyDecl(ObjCPropertyDecl *ND) { @@ -772,7 +770,6 @@ const char *clang_getCursorKindSpelling(enum CXCursorKind Kind) { case CXCursor_UnionDecl: return "UnionDecl"; case CXCursor_ClassDecl: return "ClassDecl"; case CXCursor_FieldDecl: return "FieldDecl"; - case CXCursor_FunctionDefn: return "FunctionDefn"; case CXCursor_VarDecl: return "VarDecl"; case CXCursor_ParmDecl: return "ParmDecl"; case CXCursor_ObjCInterfaceDecl: return "ObjCInterfaceDecl"; @@ -783,10 +780,8 @@ const char *clang_getCursorKindSpelling(enum CXCursorKind Kind) { case CXCursor_ObjCIvarRef: return "ObjCIvarRef"; case CXCursor_ObjCInstanceMethodDecl: return "ObjCInstanceMethodDecl"; case CXCursor_ObjCClassMethodDecl: return "ObjCClassMethodDecl"; - case CXCursor_ObjCInstanceMethodDefn: return "ObjCInstanceMethodDefn"; - case CXCursor_ObjCCategoryDefn: return "ObjCCategoryDefn"; - case CXCursor_ObjCClassMethodDefn: return "ObjCClassMethodDefn"; - case CXCursor_ObjCClassDefn: return "ObjCClassDefn"; + case CXCursor_ObjCImplementationDecl: return "ObjCImplementationDecl"; + case CXCursor_ObjCCategoryImplDecl: return "ObjCCategoryImplDecl"; case CXCursor_ObjCSuperClassRef: return "ObjCSuperClassRef"; case CXCursor_ObjCProtocolRef: return "ObjCProtocolRef"; case CXCursor_ObjCClassRef: return "ObjCClassRef"; @@ -878,16 +873,12 @@ unsigned clang_isReference(enum CXCursorKind K) { return K >= CXCursor_FirstRef && K <= CXCursor_LastRef; } -unsigned clang_isDefinition(enum CXCursorKind K) { - return K >= CXCursor_FirstDefn && K <= CXCursor_LastDefn; -} - CXCursorKind clang_getCursorKind(CXCursor C) { return C.kind; } CXDecl clang_getCursorDecl(CXCursor C) { - if (clang_isDeclaration(C.kind) || clang_isDefinition(C.kind)) + if (clang_isDeclaration(C.kind)) return getCursorDecl(C); if (clang_isReference(C.kind)) { @@ -1008,7 +999,7 @@ CXSourceRange clang_getCursorExtent(CXCursor C) { } CXCursor clang_getCursorReferenced(CXCursor C) { - if (clang_isDeclaration(C.kind) || clang_isDefinition(C.kind)) + if (clang_isDeclaration(C.kind)) return C; if (!clang_isReference(C.kind)) @@ -1046,6 +1037,238 @@ CXCursor clang_getCursorReferenced(CXCursor C) { return clang_getNullCursor(); } +CXCursor clang_getCursorDefinition(CXCursor C) { + bool WasReference = false; + if (clang_isReference(C.kind)) { + C = clang_getCursorReferenced(C); + WasReference = true; + } + + if (!clang_isDeclaration(C.kind)) + return clang_getNullCursor(); + + Decl *D = getCursorDecl(C); + if (!D) + return clang_getNullCursor(); + + switch (D->getKind()) { + // Declaration kinds that don't really separate the notions of + // declaration and definition. + case Decl::Namespace: + case Decl::Typedef: + case Decl::TemplateTypeParm: + case Decl::EnumConstant: + case Decl::Field: + case Decl::ObjCIvar: + case Decl::ObjCAtDefsField: + case Decl::ImplicitParam: + case Decl::ParmVar: + case Decl::NonTypeTemplateParm: + case Decl::TemplateTemplateParm: + case Decl::ObjCCategoryImpl: + case Decl::ObjCImplementation: + case Decl::LinkageSpec: + case Decl::ObjCPropertyImpl: + case Decl::FileScopeAsm: + case Decl::StaticAssert: + case Decl::Block: + return C; + + // Declaration kinds that don't make any sense here, but are + // nonetheless harmless. + case Decl::TranslationUnit: + case Decl::Template: + case Decl::ObjCContainer: + break; + + // Declaration kinds for which the definition is not resolvable. + case Decl::UnresolvedUsingTypename: + case Decl::UnresolvedUsingValue: + break; + + case Decl::UsingDirective: + return MakeCXCursor(cast(D)->getNominatedNamespace()); + + case Decl::NamespaceAlias: + return MakeCXCursor(cast(D)->getNamespace()); + + case Decl::Enum: + case Decl::Record: + case Decl::CXXRecord: + case Decl::ClassTemplateSpecialization: + case Decl::ClassTemplatePartialSpecialization: + if (TagDecl *Def = cast(D)->getDefinition(D->getASTContext())) + return MakeCXCursor(Def); + return clang_getNullCursor(); + + case Decl::Function: + case Decl::CXXMethod: + case Decl::CXXConstructor: + case Decl::CXXDestructor: + case Decl::CXXConversion: { + const FunctionDecl *Def = 0; + if (cast(D)->getBody(Def)) + return MakeCXCursor(const_cast(Def)); + return clang_getNullCursor(); + } + + case Decl::Var: { + VarDecl *Var = cast(D); + + // Variables with initializers have definitions. + const VarDecl *Def = 0; + if (Var->getDefinition(Def)) + return MakeCXCursor(const_cast(Def)); + + // extern and private_extern variables are not definitions. + if (Var->hasExternalStorage()) + return clang_getNullCursor(); + + // In-line static data members do not have definitions. + if (Var->isStaticDataMember() && !Var->isOutOfLine()) + return clang_getNullCursor(); + + // All other variables are themselves definitions. + return C; + } + + case Decl::FunctionTemplate: { + const FunctionDecl *Def = 0; + if (cast(D)->getTemplatedDecl()->getBody(Def)) + return MakeCXCursor(Def->getDescribedFunctionTemplate()); + return clang_getNullCursor(); + } + + case Decl::ClassTemplate: { + if (RecordDecl *Def = cast(D)->getTemplatedDecl() + ->getDefinition(D->getASTContext())) + return MakeCXCursor( + cast(Def)->getDescribedClassTemplate()); + return clang_getNullCursor(); + } + + case Decl::Using: { + UsingDecl *Using = cast(D); + CXCursor Def = clang_getNullCursor(); + for (UsingDecl::shadow_iterator S = Using->shadow_begin(), + SEnd = Using->shadow_end(); + S != SEnd; ++S) { + if (Def != clang_getNullCursor()) { + // FIXME: We have no way to return multiple results. + return clang_getNullCursor(); + } + + Def = clang_getCursorDefinition(MakeCXCursor((*S)->getTargetDecl())); + } + + return Def; + } + + case Decl::UsingShadow: + return clang_getCursorDefinition( + MakeCXCursor(cast(D)->getTargetDecl())); + + case Decl::ObjCMethod: { + ObjCMethodDecl *Method = cast(D); + if (Method->isThisDeclarationADefinition()) + return C; + + // Dig out the method definition in the associated + // @implementation, if we have it. + // FIXME: The ASTs should make finding the definition easier. + if (ObjCInterfaceDecl *Class + = dyn_cast(Method->getDeclContext())) + if (ObjCImplementationDecl *ClassImpl = Class->getImplementation()) + if (ObjCMethodDecl *Def = ClassImpl->getMethod(Method->getSelector(), + Method->isInstanceMethod())) + if (Def->isThisDeclarationADefinition()) + return MakeCXCursor(Def); + + return clang_getNullCursor(); + } + + case Decl::ObjCCategory: + if (ObjCCategoryImplDecl *Impl + = cast(D)->getImplementation()) + return MakeCXCursor(Impl); + return clang_getNullCursor(); + + case Decl::ObjCProtocol: + if (!cast(D)->isForwardDecl()) + return C; + return clang_getNullCursor(); + + case Decl::ObjCInterface: + // There are two notions of a "definition" for an Objective-C + // class: the interface and its implementation. When we resolved a + // reference to an Objective-C class, produce the @interface as + // the definition; when we were provided with the interface, + // produce the @implementation as the definition. + if (WasReference) { + if (!cast(D)->isForwardDecl()) + return C; + } else if (ObjCImplementationDecl *Impl + = cast(D)->getImplementation()) + return MakeCXCursor(Impl); + return clang_getNullCursor(); + + case Decl::ObjCProperty: + // FIXME: We don't really know where to find the + // ObjCPropertyImplDecls that implement this property. + return clang_getNullCursor(); + + case Decl::ObjCCompatibleAlias: + if (ObjCInterfaceDecl *Class + = cast(D)->getClassInterface()) + if (!Class->isForwardDecl()) + return MakeCXCursor(Class); + + return clang_getNullCursor(); + + case Decl::ObjCForwardProtocol: { + ObjCForwardProtocolDecl *Forward = cast(D); + if (Forward->protocol_size() == 1) + return clang_getCursorDefinition( + MakeCXCursor(*Forward->protocol_begin())); + + // FIXME: Cannot return multiple definitions. + return clang_getNullCursor(); + } + + case Decl::ObjCClass: { + ObjCClassDecl *Class = cast(D); + if (Class->size() == 1) { + ObjCInterfaceDecl *IFace = Class->begin()->getInterface(); + if (!IFace->isForwardDecl()) + return MakeCXCursor(IFace); + return clang_getNullCursor(); + } + + // FIXME: Cannot return multiple definitions. + return clang_getNullCursor(); + } + + case Decl::Friend: + if (NamedDecl *Friend = cast(D)->getFriendDecl()) + return clang_getCursorDefinition(MakeCXCursor(Friend)); + return clang_getNullCursor(); + + case Decl::FriendTemplate: + if (NamedDecl *Friend = cast(D)->getFriendDecl()) + return clang_getCursorDefinition(MakeCXCursor(Friend)); + return clang_getNullCursor(); + } + + return clang_getNullCursor(); +} + +unsigned clang_isCursorDefinition(CXCursor C) { + if (!clang_isDeclaration(C.kind)) + return 0; + + return clang_getCursorDefinition(C) == C; +} + void clang_getDefinitionSpellingAndExtent(CXCursor C, const char **startBuf, const char **endBuf, diff --git a/tools/CIndex/CIndex.exports b/tools/CIndex/CIndex.exports index 71522fd3ed..0460ba0d59 100644 --- a/tools/CIndex/CIndex.exports +++ b/tools/CIndex/CIndex.exports @@ -13,6 +13,7 @@ _clang_getCompletionChunkKind _clang_getCompletionChunkText _clang_getCursor _clang_getCursorDecl +_clang_getCursorDefinition _clang_getCursorExtent _clang_getCursorFromDecl _clang_getCursorKind @@ -36,8 +37,8 @@ _clang_getFileTime _clang_getNullCursor _clang_getNumCompletionChunks _clang_getTranslationUnitSpelling +_clang_isCursorDefinition _clang_isDeclaration -_clang_isDefinition _clang_isInvalid _clang_isReference _clang_loadDeclaration diff --git a/tools/CIndex/CXCursor.cpp b/tools/CIndex/CXCursor.cpp index 747b1a1390..00636f74d5 100644 --- a/tools/CIndex/CXCursor.cpp +++ b/tools/CIndex/CXCursor.cpp @@ -39,17 +39,16 @@ static CXCursorKind GetCursorKind(Decl *D) { case Decl::EnumConstant: return CXCursor_EnumConstantDecl; case Decl::Field: return CXCursor_FieldDecl; case Decl::Function: - return cast(D)->isThisDeclarationADefinition() - ? CXCursor_FunctionDefn : CXCursor_FunctionDecl; + return CXCursor_FunctionDecl; case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl; - case Decl::ObjCCategoryImpl: return CXCursor_ObjCCategoryDefn; + case Decl::ObjCCategoryImpl: return CXCursor_ObjCCategoryImplDecl; case Decl::ObjCClass: // FIXME return CXCursor_NotImplemented; case Decl::ObjCForwardProtocol: // FIXME return CXCursor_NotImplemented; - case Decl::ObjCImplementation: return CXCursor_ObjCClassDefn; + case Decl::ObjCImplementation: return CXCursor_ObjCImplementationDecl; case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl; case Decl::ObjCIvar: return CXCursor_ObjCIvarDecl; case Decl::ObjCMethod: @@ -160,11 +159,8 @@ ASTContext &cxcursor::getCursorContext(CXCursor Cursor) { case CXCursor_ObjCIvarDecl: case CXCursor_ObjCInstanceMethodDecl: case CXCursor_ObjCClassMethodDecl: - case CXCursor_FunctionDefn: - case CXCursor_ObjCClassDefn: - case CXCursor_ObjCCategoryDefn: - case CXCursor_ObjCInstanceMethodDefn: - case CXCursor_ObjCClassMethodDefn: + case CXCursor_ObjCImplementationDecl: + case CXCursor_ObjCCategoryImplDecl: return static_cast(Cursor.data[0])->getASTContext(); case CXCursor_ObjCSuperClassRef: diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c index 34332d3e40..391f577bc4 100644 --- a/tools/c-index-test/c-index-test.c +++ b/tools/c-index-test/c-index-test.c @@ -59,6 +59,9 @@ static void PrintCursor(CXCursor Cursor) { CXSourceLocation Loc = clang_getCursorLocation(Referenced); printf(":%d:%d", Loc.line, Loc.column); } + + if (clang_isCursorDefinition(Cursor)) + printf(" (Definition)"); } } @@ -125,7 +128,8 @@ static void FunctionScanVisitor(CXTranslationUnit Unit, CXCursor Cursor, unsigned startLine, startColumn, endLine, endColumn, curLine, curColumn; CXCursor Ref; - if (Cursor.kind != CXCursor_FunctionDefn) + if (Cursor.kind != CXCursor_FunctionDecl || + !clang_isCursorDefinition(Cursor)) return; clang_getDefinitionSpellingAndExtent(Cursor, &startBuf, &endBuf,