// 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
{
}
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]
#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"
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;
}