Teach clang_getCursorLocation() to return the locations of references
rather than the locations that refer to.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@93812 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/tools/CIndex/CIndex.cpp b/tools/CIndex/CIndex.cpp
index ba0e260..e48581a 100644
--- a/tools/CIndex/CIndex.cpp
+++ b/tools/CIndex/CIndex.cpp
@@ -350,58 +350,6 @@
   Call(CXCursor_VarDecl, ND);
 }
 
-static SourceLocation getLocationFromCursor(CXCursor C,
-                                            SourceManager &SourceMgr,
-                                            NamedDecl *ND) {
-  if (clang_isReference(C.kind)) {
-    
-    if (Decl *D = getCursorReferringDecl(C))
-      return D->getLocation();
-    
-    switch (C.kind) {
-    case CXCursor_ObjCClassRef:
-      return getCursorObjCClassRef(C).second;
-    case CXCursor_ObjCSuperClassRef:
-      return getCursorObjCSuperClassRef(C).second;
-    case CXCursor_ObjCProtocolRef:
-      return getCursorObjCProtocolRef(C).second;
-    case CXCursor_ObjCSelectorRef: {
-      ObjCMessageExpr *OME = dyn_cast<ObjCMessageExpr>(getCursorStmt(C));
-      assert(OME && "getLocationFromCursor(): Missing message expr");
-      return OME->getLeftLoc(); /* FIXME: should be a range */
-    }
-    case CXCursor_VarRef:
-    case CXCursor_FunctionRef:
-    case CXCursor_EnumConstantRef: {
-      DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(getCursorStmt(C));
-      assert(DRE && "getLocationFromCursor(): Missing decl ref expr");
-      return DRE->getLocation();
-    }
-    default:
-      return SourceLocation();
-    }
-  } else { // We have a declaration or a definition.
-    SourceLocation SLoc;
-    switch (ND->getKind()) {
-    case Decl::ObjCInterface: {
-      SLoc = dyn_cast<ObjCInterfaceDecl>(ND)->getClassLoc();
-      break;
-    }
-    case Decl::ObjCProtocol: {
-      SLoc = ND->getLocation(); /* FIXME: need to get the name location. */
-      break;
-    }
-    default: {
-      SLoc = ND->getLocation();
-      break;
-    }
-    }
-    if (SLoc.isInvalid())
-      return SourceLocation();
-    return SourceMgr.getSpellingLoc(SLoc); // handles macro instantiations.
-  }
-}
-
 CXString CIndexer::createCXString(const char *String, bool DupString){
   CXString Str;
   if (DupString) {
@@ -791,12 +739,12 @@
     }
     case CXCursor_ObjCProtocolRef: {
       ObjCProtocolDecl *OID = getCursorObjCProtocolRef(C).first;
-      assert(OID && "getLocationFromCursor(): Missing protocol decl");
+      assert(OID && "getCursorSpelling(): Missing protocol decl");
       return CIndexer::createCXString(OID->getIdentifier()->getNameStart());
     }
     case CXCursor_ObjCSelectorRef: {
       ObjCMessageExpr *OME = dyn_cast<ObjCMessageExpr>(getCursorStmt(C));
-      assert(OME && "getLocationFromCursor(): Missing message expr");
+      assert(OME && "getCursorSpelling(): Missing message expr");
       return CIndexer::createCXString(OME->getSelector().getAsString().c_str(),
                                       true);
     }
@@ -804,7 +752,7 @@
     case CXCursor_FunctionRef:
     case CXCursor_EnumConstantRef: {
       DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(getCursorStmt(C));
-      assert(DRE && "getLocationFromCursor(): Missing decl ref expr");
+      assert(DRE && "getCursorSpelling(): Missing decl ref expr");
       return CIndexer::createCXString(DRE->getDecl()->getIdentifier()
                                       ->getNameStart());
     }
@@ -888,9 +836,11 @@
   if (Dcl) {
     if (Stm) {
       if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Stm))
-        return MakeCXCursor(TranslateDeclRefExpr(DRE), Dcl, Stm);
+        return MakeCXCursor(TranslateDeclRefExpr(DRE), Dcl, Stm,
+                            CXXUnit->getASTContext());
       else if (ObjCMessageExpr *MExp = dyn_cast<ObjCMessageExpr>(Stm))
-        return MakeCXCursor(CXCursor_ObjCSelectorRef, Dcl, MExp);
+        return MakeCXCursor(CXCursor_ObjCSelectorRef, Dcl, MExp,
+                            CXXUnit->getASTContext());
       // Fall through...treat as a decl, not a ref.
     }
     if (ALoc.isNamedRef()) {
@@ -952,8 +902,51 @@
 
 CXSourceLocation clang_getCursorLocation(CXCursor C) {
   if (clang_isReference(C.kind)) {
-    // FIXME: Return the location of the reference, not of the underlying
-    // declaration (which may not even exist!).
+    switch (C.kind) {
+    case CXCursor_ObjCSuperClassRef: {       
+      std::pair<ObjCInterfaceDecl *, SourceLocation> P
+        = getCursorObjCSuperClassRef(C);
+      SourceManager &SM = P.first->getASTContext().getSourceManager();
+      return translateSourceLocation(SM, P.second);
+    }
+
+    case CXCursor_ObjCProtocolRef: {       
+      std::pair<ObjCProtocolDecl *, SourceLocation> P
+        = getCursorObjCProtocolRef(C);
+      SourceManager &SM = P.first->getASTContext().getSourceManager();
+      return translateSourceLocation(SM, P.second);
+    }
+
+    case CXCursor_ObjCClassRef: {       
+      std::pair<ObjCInterfaceDecl *, SourceLocation> P
+        = getCursorObjCClassRef(C);
+      SourceManager &SM = P.first->getASTContext().getSourceManager();
+      return translateSourceLocation(SM, P.second);
+    }
+      
+    case CXCursor_ObjCSelectorRef:
+    case CXCursor_ObjCIvarRef:
+    case CXCursor_VarRef:
+    case CXCursor_FunctionRef:
+    case CXCursor_EnumConstantRef:
+    case CXCursor_MemberRef: {
+      Expr *E = getCursorExpr(C);
+      SourceManager &SM = getCursorContext(C).getSourceManager();
+      if (ObjCMessageExpr *Msg = dyn_cast<ObjCMessageExpr>(E))
+        return translateSourceLocation(SM, /*FIXME:*/Msg->getLeftLoc());
+      if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
+        return translateSourceLocation(SM, DRE->getLocation());
+      if (MemberExpr *Member = dyn_cast<MemberExpr>(E))
+        return translateSourceLocation(SM, Member->getMemberLoc());
+      if (ObjCIvarRefExpr *Ivar = dyn_cast<ObjCIvarRefExpr>(E))
+        return translateSourceLocation(SM, Ivar->getLocation());
+      return translateSourceLocation(SM, E->getLocStart());
+    }
+        
+    default:
+      // FIXME: Need a way to enumerate all non-reference cases.
+      llvm_unreachable("Missed a reference kind");
+    }
   }
   
   if (!getCursorDecl(C)) {
@@ -961,10 +954,12 @@
     return empty;
   }
 
-  NamedDecl *ND = static_cast<NamedDecl *>(getCursorDecl(C));
-  SourceManager &SM = ND->getASTContext().getSourceManager();
-  
-  return translateSourceLocation(SM, getLocationFromCursor(C, SM, ND));
+  Decl *D = getCursorDecl(C);
+  SourceManager &SM = D->getASTContext().getSourceManager();
+  SourceLocation Loc = D->getLocation();
+  if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(D))
+    Loc = Class->getClassLoc();
+  return translateSourceLocation(SM, Loc);
 }
   
 void clang_getDefinitionSpellingAndExtent(CXCursor C,