Implement clang_getCursorExtent, which provides a source range for the
cursor itself. In particular, for references this returns the source
range of the reference rather than the source range of the thing it
refers to.

Switch c-index-test from clang_getDeclExtent (which will eventually be
deprecated and removed) over to clang_getCursorExtent. The source
ranges we print for references now make sense; fix up the tests
appropriately.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@93823 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/tools/CIndex/CIndex.cpp b/tools/CIndex/CIndex.cpp
index e48581a..9e74083 100644
--- a/tools/CIndex/CIndex.cpp
+++ b/tools/CIndex/CIndex.cpp
@@ -130,6 +130,55 @@
   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.
 //===----------------------------------------------------------------------===//
@@ -609,57 +658,7 @@
 }
   
 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) {
@@ -961,6 +960,52 @@
     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,