// 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=4:1:11: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: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=4:1:11: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: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: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:17: ObjCProtocolRef=Proto:24:1 [Extent=24:1:26: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=13:1:17:4]
-// CHECK: c-index-api-loadTU-test.m:32:23: ObjCProtocolRef=SubP:28:1 [Extent=28:1:30: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: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]
// CHECK: c-index-api-loadTU-test.m:41:1: EnumDecl=:41:1 [Extent=41:1:43:1]
return Result;
}
+/// \brief Translate a Clang source range into a CIndex source range.
+static CXSourceRange translateSourceRange(ASTContext &Context,
+ SourceRange R) {
+ if (R.isInvalid()) {
+ CXSourceRange extent = { { 0, 0, 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.
+
+ SourceManager &SM = Context.getSourceManager();
+ SourceLocation Begin = SM.getInstantiationLoc(R.getBegin());
+ SourceLocation End = SM.getInstantiationLoc(R.getEnd());
+
+ // 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;
+
+ 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.
+ EndColNo += Lexer::MeasureTokenLength(End, SM, Context.getLangOptions());
+ }
+
+ // Package up the line/column data and return to the caller.
+ const FileEntry *BeginFile = SM.getFileEntryForID(SM.getFileID(Begin));
+ const FileEntry *EndFile = SM.getFileEntryForID(SM.getFileID(End));
+ CXSourceRange extent = { { (void *)BeginFile, StartLineNo, StartColNo },
+ { (void *)EndFile, EndLineNo, EndColNo } };
+ return extent;
+}
+
//===----------------------------------------------------------------------===//
// Visitors.
//===----------------------------------------------------------------------===//
}
CXSourceRange clang_getDeclExtent(CXDecl AnonDecl) {
- assert(AnonDecl && "Passed null CXDecl");
- NamedDecl *ND = static_cast<NamedDecl *>(AnonDecl);
- SourceManager &SM = ND->getASTContext().getSourceManager();
- SourceRange R = ND->getSourceRange();
-
- SourceLocation Begin = SM.getInstantiationLoc(R.getBegin());
- SourceLocation End = SM.getInstantiationLoc(R.getEnd());
-
- if (!Begin.isValid()) {
- CXSourceRange extent = { { 0, 0, 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.
-
- // 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.
- const FileEntry *FEntry = SM.getFileEntryForID(SM.getFileID(Begin));
- CXSourceRange extent = { { (void *)FEntry, StartLineNo, StartColNo },
- { (void *)FEntry, EndLineNo, EndColNo } };
- return extent;
+ return clang_getCursorExtent(clang_getCursorFromDecl(AnonDecl));
}
const char *clang_getDeclSource(CXDecl AnonDecl) {
Loc = Class->getClassLoc();
return translateSourceLocation(SM, Loc);
}
+
+CXSourceRange clang_getCursorExtent(CXCursor C) {
+ if (clang_isReference(C.kind)) {
+ switch (C.kind) {
+ case CXCursor_ObjCSuperClassRef: {
+ std::pair<ObjCInterfaceDecl *, SourceLocation> P
+ = getCursorObjCSuperClassRef(C);
+ return translateSourceRange(P.first->getASTContext(), P.second);
+ }
+
+ case CXCursor_ObjCProtocolRef: {
+ std::pair<ObjCProtocolDecl *, SourceLocation> P
+ = getCursorObjCProtocolRef(C);
+ return translateSourceRange(P.first->getASTContext(), P.second);
+ }
+
+ case CXCursor_ObjCClassRef: {
+ std::pair<ObjCInterfaceDecl *, SourceLocation> P
+ = getCursorObjCClassRef(C);
+
+ return translateSourceRange(P.first->getASTContext(), P.second);
+ }
+
+ case CXCursor_ObjCSelectorRef:
+ case CXCursor_ObjCIvarRef:
+ case CXCursor_VarRef:
+ case CXCursor_FunctionRef:
+ case CXCursor_EnumConstantRef:
+ case CXCursor_MemberRef:
+ return translateSourceRange(getCursorContext(C),
+ getCursorExpr(C)->getSourceRange());
+
+ default:
+ // FIXME: Need a way to enumerate all non-reference cases.
+ llvm_unreachable("Missed a reference kind");
+ }
+ }
+
+ if (!getCursorDecl(C)) {
+ CXSourceRange empty = { { 0, 0, 0 }, { 0, 0, 0 } };
+ return empty;
+ }
+
+ Decl *D = getCursorDecl(C);
+ return translateSourceRange(D->getASTContext(), D->getSourceRange());
+}
void clang_getDefinitionSpellingAndExtent(CXCursor C,
const char **startBuf,