diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h index d853072661eb..12dd76850b67 100644 --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -346,8 +346,8 @@ typedef struct CXDeclExtent { /* clang_getDeclExtent() returns the physical extent of a declaration. The * beginning line/column pair points to the start of the first token in the - * declaration, and the ending line/column pair points the start of the last - * token in the declaration. + * declaration, and the ending line/column pair points to the last character in + * the last token of the declaration. */ CINDEX_LINKAGE CXSourceExtent clang_getDeclExtent(CXDecl); diff --git a/clang/test/Index/c-index-api-loadTU-test.m b/clang/test/Index/c-index-api-loadTU-test.m index fdcbe556714f..aa0d8d4f4d9f 100644 --- a/clang/test/Index/c-index-api-loadTU-test.m +++ b/clang/test/Index/c-index-api-loadTU-test.m @@ -1,21 +1,6 @@ // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi -fblocks -emit-pch -x objective-c %s -o %t.ast // RUN: c-index-test -test-load-tu %t.ast all | FileCheck %s - - - - - - - - - - - - - - - @interface Foo { } @@ -68,32 +53,32 @@ int main (int argc, const char * argv[]) { main(someEnum, (const char **)bee); } -// CHECK: c-index-api-loadTU-test.m:19:12: ObjCInterfaceDecl=Foo:19:1 [Context=c-index-api-loadTU-test.m] [Extent=19:1:26:1] -// CHECK: c-index-api-loadTU-test.m:23:1: ObjCInstanceMethodDecl=foo:23:1 [Context=Foo] [Extent=23:1:23:6] -// CHECK: c-index-api-loadTU-test.m:24:1: ObjCClassMethodDecl=fooC:24:1 [Context=Foo] [Extent=24:1:24:7] -// CHECK: c-index-api-loadTU-test.m:28:12: ObjCInterfaceDecl=Bar:28:1 [Context=c-index-api-loadTU-test.m] [Extent=28:1:32:1] -// CHECK: c-index-api-loadTU-test.m:28:18: ObjCSuperClassRef=Foo:28:1 [Context=Bar] [Extent=28:1:32:1] -// CHECK: c-index-api-loadTU-test.m:34:1: ObjCCategoryDecl=FooCat:34:1 [Context=c-index-api-loadTU-test.m] [Extent=34:1:37:1] -// CHECK: c-index-api-loadTU-test.m:19:1: ObjCClassRef=Foo:34:1 [Context=FooCat] [Extent=34:1:37:1] -// CHECK: c-index-api-loadTU-test.m:35:1: ObjCInstanceMethodDecl=catMethodWithFloat::35:1 [Context=FooCat] [Extent=35:1:35:40] -// CHECK: c-index-api-loadTU-test.m:36:1: ObjCInstanceMethodDecl=floatMethod:36:1 [Context=FooCat] [Extent=36:1:36:22] -// CHECK: c-index-api-loadTU-test.m:39:1: ObjCProtocolDecl=Proto:39:1 [Context=c-index-api-loadTU-test.m] [Extent=39:1:41:1] -// CHECK: c-index-api-loadTU-test.m:40:1: ObjCInstanceMethodDecl=pMethod:40:1 [Context=Proto] [Extent=40:1:40:10] -// CHECK: c-index-api-loadTU-test.m:43:1: ObjCProtocolDecl=SubP:43:1 [Context=c-index-api-loadTU-test.m] [Extent=43:1:45:1] -// CHECK: c-index-api-loadTU-test.m:39:1: ObjCProtocolRef=Proto:39:1 [Context=SubP] [Extent=39:1:41:1] -// CHECK: c-index-api-loadTU-test.m:44:1: ObjCInstanceMethodDecl=spMethod:44:1 [Context=SubP] [Extent=44:1:44:11] -// CHECK: c-index-api-loadTU-test.m:47:12: ObjCInterfaceDecl=Baz:47:1 [Context=c-index-api-loadTU-test.m] [Extent=47:1:54:1] -// CHECK: c-index-api-loadTU-test.m:47:18: ObjCSuperClassRef=Bar:47:1 [Context=Baz] [Extent=47:1:54:1] -// CHECK: c-index-api-loadTU-test.m:43:1: ObjCProtocolRef=SubP:43:1 [Context=Baz] [Extent=43:1:45:1] -// CHECK: c-index-api-loadTU-test.m:49:9: ObjCIvarDecl=_anIVar:49:9 [Context=Baz] [Extent=49:9:49:9] -// CHECK: c-index-api-loadTU-test.m:52:1: ObjCInstanceMethodDecl=bazMethod:52:1 [Context=Baz] [Extent=52:1:52:20] -// CHECK: c-index-api-loadTU-test.m:56:1: EnumDecl=:56:1 [Context=c-index-api-loadTU-test.m] [Extent=56:1:58:1] -// CHECK: c-index-api-loadTU-test.m:57:3: EnumConstantDecl=someEnum:57:3 [Context=] [Extent=57:3:57:3] -// CHECK: c-index-api-loadTU-test.m:60:5: FunctionDefn=main [Context=c-index-api-loadTU-test.m] [Extent=60:5:69:1] -// CHECK: c-index-api-loadTU-test.m:60:15: ParmDecl=argc:60:15 [Context=main] [Extent=60:15:60:15] -// CHECK: c-index-api-loadTU-test.m:60:34: ParmDecl=argv:60:34 [Context=main] [Extent=60:34:60:34] -// CHECK: c-index-api-loadTU-test.m:61:8: VarDecl=bee:61:8 [Context=main] [Extent=61:8:61:8] -// CHECK: c-index-api-loadTU-test.m:62:5: VarDecl=a:62:5 [Context=main] [Extent=62:5:62:17] -// CHECK: c-index-api-loadTU-test.m:63:12: VarDecl=c:63:12 [Context=main] [Extent=63:12:63:25] -// CHECK: c-index-api-loadTU-test.m:64:13: VarDecl=d:64:13 [Context=main] [Extent=64:13:64:13] +// CHECK: c-index-api-loadTU-test.m:4:12: ObjCInterfaceDecl=Foo:4:1 [Context=c-index-api-loadTU-test.m] [Extent=4:1:11:1] +// CHECK: c-index-api-loadTU-test.m:8:1: ObjCInstanceMethodDecl=foo:8:1 [Context=Foo] [Extent=8:1:8:6] +// CHECK: c-index-api-loadTU-test.m:9:1: ObjCClassMethodDecl=fooC:9:1 [Context=Foo] [Extent=9:1:9:7] +// CHECK: c-index-api-loadTU-test.m:13:12: ObjCInterfaceDecl=Bar:13:1 [Context=c-index-api-loadTU-test.m] [Extent=13:1:17:1] +// CHECK: c-index-api-loadTU-test.m:13:18: ObjCSuperClassRef=Foo:13:1 [Context=Bar] [Extent=13:1:17:1] +// CHECK: c-index-api-loadTU-test.m:19:1: ObjCCategoryDecl=FooCat:19:1 [Context=c-index-api-loadTU-test.m] [Extent=19:1:22:1] +// CHECK: c-index-api-loadTU-test.m:4:1: ObjCClassRef=Foo:19:1 [Context=FooCat] [Extent=19:1:22:1] +// CHECK: c-index-api-loadTU-test.m:20:1: ObjCInstanceMethodDecl=catMethodWithFloat::20:1 [Context=FooCat] [Extent=20:1:20:40] +// CHECK: c-index-api-loadTU-test.m:21:1: ObjCInstanceMethodDecl=floatMethod:21:1 [Context=FooCat] [Extent=21:1:21:22] +// CHECK: c-index-api-loadTU-test.m:24:1: ObjCProtocolDecl=Proto:24:1 [Context=c-index-api-loadTU-test.m] [Extent=24:1:26:1] +// CHECK: c-index-api-loadTU-test.m:25:1: ObjCInstanceMethodDecl=pMethod:25:1 [Context=Proto] [Extent=25:1:25:10] +// CHECK: c-index-api-loadTU-test.m:28:1: ObjCProtocolDecl=SubP:28:1 [Context=c-index-api-loadTU-test.m] [Extent=28:1:30:1] +// CHECK: c-index-api-loadTU-test.m:24:1: ObjCProtocolRef=Proto:24:1 [Context=SubP] [Extent=24:1:26:1] +// CHECK: c-index-api-loadTU-test.m:29:1: ObjCInstanceMethodDecl=spMethod:29:1 [Context=SubP] [Extent=29:1:29:11] +// CHECK: c-index-api-loadTU-test.m:32:12: ObjCInterfaceDecl=Baz:32:1 [Context=c-index-api-loadTU-test.m] [Extent=32:1:39:1] +// CHECK: c-index-api-loadTU-test.m:32:18: ObjCSuperClassRef=Bar:32:1 [Context=Baz] [Extent=32:1:39:1] +// CHECK: c-index-api-loadTU-test.m:28:1: ObjCProtocolRef=SubP:28:1 [Context=Baz] [Extent=28:1:30:1] +// CHECK: c-index-api-loadTU-test.m:34:9: ObjCIvarDecl=_anIVar:34:9 [Context=Baz] [Extent=34:9:34:15] +// CHECK: c-index-api-loadTU-test.m:37:1: ObjCInstanceMethodDecl=bazMethod:37:1 [Context=Baz] [Extent=37:1:37:20] +// CHECK: c-index-api-loadTU-test.m:41:1: EnumDecl=:41:1 [Context=c-index-api-loadTU-test.m] [Extent=41:1:43:1] +// CHECK: c-index-api-loadTU-test.m:42:3: EnumConstantDecl=someEnum:42:3 [Context=] [Extent=42:3:42:10] +// CHECK: c-index-api-loadTU-test.m:45:5: FunctionDefn=main [Context=c-index-api-loadTU-test.m] [Extent=45:5:54:1] +// CHECK: c-index-api-loadTU-test.m:45:15: ParmDecl=argc:45:15 [Context=main] [Extent=45:15:45:18] +// CHECK: c-index-api-loadTU-test.m:45:34: ParmDecl=argv:45:34 [Context=main] [Extent=45:34:45:37] +// CHECK: c-index-api-loadTU-test.m:46:8: VarDecl=bee:46:8 [Context=main] [Extent=46:8:46:10] +// CHECK: c-index-api-loadTU-test.m:47:5: VarDecl=a:47:5 [Context=main] [Extent=47:5:47:17] +// CHECK: c-index-api-loadTU-test.m:48:12: VarDecl=c:48:12 [Context=main] [Extent=48:12:48:25] +// CHECK: c-index-api-loadTU-test.m:49:13: VarDecl=d:49:13 [Context=main] [Extent=49:13:49:13] diff --git a/clang/tools/CIndex/CIndex.cpp b/clang/tools/CIndex/CIndex.cpp index e6b3d60e19a6..2c3f7373a31f 100644 --- a/clang/tools/CIndex/CIndex.cpp +++ b/clang/tools/CIndex/CIndex.cpp @@ -16,6 +16,7 @@ #include "clang/AST/DeclVisitor.h" #include "clang/AST/StmtVisitor.h" +#include "clang/Lex/Lexer.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/System/Program.h" @@ -627,19 +628,53 @@ unsigned clang_getDeclColumn(CXDecl AnonDecl) { CXDeclExtent clang_getDeclExtent(CXDecl AnonDecl) { assert(AnonDecl && "Passed null CXDecl"); NamedDecl *ND = static_cast(AnonDecl); - SourceManager &SourceMgr = ND->getASTContext().getSourceManager(); + SourceManager &SM = ND->getASTContext().getSourceManager(); SourceRange R = ND->getSourceRange(); - CXDeclExtent extent; + SourceLocation Begin = SM.getInstantiationLoc(R.getBegin()); + SourceLocation End = SM.getInstantiationLoc(R.getEnd()); + + if (!Begin.isValid()) { + CXDeclExtent extent = { { 0, 0 }, { 0, 0 } }; + return extent; + } - SourceLocation L = SourceMgr.getSpellingLoc(R.getBegin()); - extent.begin.line = SourceMgr.getSpellingLineNumber(L); - extent.begin.column = SourceMgr.getSpellingColumnNumber(L); + // FIXME: This is largely copy-paste from + ///TextDiagnosticPrinter::HighlightRange. When it is clear that this is + // what we want the two routines should be refactored. - L = SourceMgr.getSpellingLoc(R.getEnd()); - extent.end.line = SourceMgr.getSpellingLineNumber(L); - extent.end.column = SourceMgr.getSpellingColumnNumber(L); + // If the End location and the start location are the same and are a macro + // location, then the range was something that came from a macro expansion + // or _Pragma. If this is an object-like macro, the best we can do is to + // get the range. If this is a function-like macro, we'd also like to + // get the arguments. + if (Begin == End && R.getEnd().isMacroID()) + End = SM.getInstantiationRange(R.getEnd()).second; + + assert(SM.getFileID(Begin) == SM.getFileID(End)); + unsigned StartLineNo = SM.getInstantiationLineNumber(Begin); + unsigned EndLineNo = SM.getInstantiationLineNumber(End); + // Compute the column number of the start. Keep the column based at 1. + unsigned StartColNo = SM.getInstantiationColumnNumber(Begin); + + // Compute the column number of the end. + unsigned EndColNo = SM.getInstantiationColumnNumber(End); + if (EndColNo) { + // Offset the end column by 1 so that we point to the last character + // in the last token. + --EndColNo; + + // Add in the length of the token, so that we cover multi-char tokens. + ASTContext &Ctx = ND->getTranslationUnitDecl()->getASTContext(); + const LangOptions &LOpts = Ctx.getLangOptions(); + + EndColNo += Lexer::MeasureTokenLength(End, SM, LOpts); + } + + // Package up the line/column data and return to the caller. + CXDeclExtent extent = { { StartLineNo, StartColNo }, + { EndLineNo, EndColNo } }; return extent; }