]> granicus.if.org Git - clang/commitdiff
Change clang_getDeclExtent() to have the endpoint point to the last character in...
authorTed Kremenek <kremenek@apple.com>
Wed, 6 Jan 2010 23:43:31 +0000 (23:43 +0000)
committerTed Kremenek <kremenek@apple.com>
Wed, 6 Jan 2010 23:43:31 +0000 (23:43 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@92869 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang-c/Index.h
test/Index/c-index-api-loadTU-test.m
tools/CIndex/CIndex.cpp

index d853072661ebfd58a6f30a03f1d1c73ce7146ef2..12dd76850b6720a3b082c9e6767cc99dfc9bb772 100644 (file)
@@ -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);
 
index fdcbe556714fb5979ef81cdc49d1b04984328a65..aa0d8d4f4d9f74e9cd96bcf0c8be5786ee0fb70e 100644 (file)
@@ -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]
 
index e6b3d60e19a6bf8fcde2d8e00f65987415a133aa..2c3f7373a31fb92961223730f8db4ecf67df9bcf 100644 (file)
@@ -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<NamedDecl *>(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;
+  }
+  
+  // 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.
   
-  SourceLocation L = SourceMgr.getSpellingLoc(R.getBegin());
-  extent.begin.line = SourceMgr.getSpellingLineNumber(L);
-  extent.begin.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);
   
-  L = SourceMgr.getSpellingLoc(R.getEnd());
-  extent.end.line = SourceMgr.getSpellingLineNumber(L);
-  extent.end.column = SourceMgr.getSpellingColumnNumber(L);
+  // 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;  
 }