Give ObjCClassRef cursors a sane representation, which is encapsulated
in CXCursor.cpp. With this sane representation, fix the class
reference that is part of Objective-C category declarations so that
the cursor's location matches up with the reference, not the class
being referred to.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@93640 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/tools/CIndex/CIndex.cpp b/tools/CIndex/CIndex.cpp
index c08243e..36919f7 100644
--- a/tools/CIndex/CIndex.cpp
+++ b/tools/CIndex/CIndex.cpp
@@ -261,7 +261,9 @@
 
 void CDeclVisitor::VisitObjCCategoryDecl(ObjCCategoryDecl *ND) {
   // Issue callbacks for the containing class.
-  Call(CXCursor_ObjCClassRef, ND);
+  Callback(CDecl, 
+           MakeCursorObjCClassRef(ND->getClassInterface(), ND->getLocation()),
+           CData);
   ObjCCategoryDecl::protocol_loc_iterator PL = ND->protocol_loc_begin();
   for (ObjCCategoryDecl::protocol_iterator I = ND->protocol_begin(),
          E = ND->protocol_end(); I != E; ++I, ++PL)
@@ -340,15 +342,8 @@
       return D->getLocation();
     
     switch (C.kind) {
-    case CXCursor_ObjCClassRef: {
-      if (isa<ObjCInterfaceDecl>(ND)) {
-        NamedDecl *parentDecl = getCursorInterfaceParent(C);
-        return parentDecl->getLocation();
-      }
-      ObjCCategoryDecl *OID = dyn_cast<ObjCCategoryDecl>(ND);
-      assert(OID && "clang_getCursorLine(): Missing category decl");
-      return OID->getClassInterface()->getLocation();
-    }
+    case CXCursor_ObjCClassRef:
+      return getCursorObjCClassRef(C).second;
     case CXCursor_ObjCSuperClassRef:
       return getCursorObjCSuperClassRef(C).second;
     case CXCursor_ObjCProtocolRef:
@@ -768,13 +763,8 @@
       return CIndexer::createCXString(Super->getIdentifier()->getNameStart());
     }
     case CXCursor_ObjCClassRef: {
-      if (ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(ND))
-        return CIndexer::createCXString(OID->getIdentifier()->getNameStart());
-
-      ObjCCategoryDecl *OCD = dyn_cast<ObjCCategoryDecl>(ND);
-      assert(OCD && "clang_getCursorLine(): Missing category decl");
-      return CIndexer::createCXString(OCD->getClassInterface()->getIdentifier()
-                            ->getNameStart());
+      ObjCInterfaceDecl *Class = getCursorObjCClassRef(C).first;
+      return CIndexer::createCXString(Class->getIdentifier()->getNameStart());
     }
     case CXCursor_ObjCProtocolRef: {
       ObjCProtocolDecl *OID = getCursorObjCProtocolRef(C).first;
@@ -881,10 +871,8 @@
       // Fall through...treat as a decl, not a ref.
     }
     if (ALoc.isNamedRef()) {
-      if (isa<ObjCInterfaceDecl>(Dcl)) {
-        CXCursor C = { CXCursor_ObjCClassRef, { Dcl, ALoc.getParentDecl(), 0 }};
-        return C;
-      }
+      if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(Dcl))
+        return MakeCursorObjCClassRef(Class, ALoc.AsNamedRef().Loc);
       if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(Dcl))
         return MakeCursorObjCProtocolRef(Proto, ALoc.AsNamedRef().Loc);
     }
@@ -931,13 +919,10 @@
     return getCursorDecl(C);
 
   if (clang_isReference(C.kind)) {
-    if (getCursorStmt(C)) {
-      if (C.kind == CXCursor_ObjCClassRef)
-        return getCursorStmt(C);
-      else
-        return getDeclFromExpr(getCursorStmt(C));
-    } else
-      return getCursorDecl(C);
+    if (getCursorStmt(C))
+      return getDeclFromExpr(getCursorStmt(C));
+
+    return getCursorDecl(C);
   }
   return 0;
 }
diff --git a/tools/CIndex/CXCursor.cpp b/tools/CIndex/CXCursor.cpp
index 01d809a..8211cb0 100644
--- a/tools/CIndex/CXCursor.cpp
+++ b/tools/CIndex/CXCursor.cpp
@@ -105,6 +105,21 @@
                                       reinterpret_cast<uintptr_t>(C.data[1])));
 }
 
+CXCursor cxcursor::MakeCursorObjCClassRef(ObjCInterfaceDecl *Class, 
+                                         SourceLocation Loc) {
+  void *RawLoc = reinterpret_cast<void *>(Loc.getRawEncoding());
+  CXCursor C = { CXCursor_ObjCClassRef, { Class, RawLoc, 0 } };
+  return C;    
+}
+
+std::pair<ObjCInterfaceDecl *, SourceLocation> 
+cxcursor::getCursorObjCClassRef(CXCursor C) {
+  assert(C.kind == CXCursor_ObjCClassRef);
+  return std::make_pair(static_cast<ObjCInterfaceDecl *>(C.data[0]),
+           SourceLocation::getFromRawEncoding(
+                                      reinterpret_cast<uintptr_t>(C.data[1])));
+}
+
 Decl *cxcursor::getCursorDecl(CXCursor Cursor) {
   return (Decl *)Cursor.data[0];
 }
@@ -115,7 +130,8 @@
 
 Stmt *cxcursor::getCursorStmt(CXCursor Cursor) {
   if (Cursor.kind == CXCursor_ObjCSuperClassRef ||
-      Cursor.kind == CXCursor_ObjCProtocolRef)
+      Cursor.kind == CXCursor_ObjCProtocolRef ||
+      Cursor.kind == CXCursor_ObjCClassRef)
     return 0;
 
   return (Stmt *)Cursor.data[1];
@@ -125,13 +141,6 @@
   return (Decl *)Cursor.data[2];
 }
 
-NamedDecl *cxcursor::getCursorInterfaceParent(CXCursor Cursor) {
-  assert(Cursor.kind == CXCursor_ObjCClassRef);
-  assert(isa<ObjCInterfaceDecl>(getCursorDecl(Cursor)));
-  // FIXME: This is a hack (storing the parent decl in the stmt slot).
-  return static_cast<NamedDecl *>(Cursor.data[1]);
-}
-
 bool cxcursor::operator==(CXCursor X, CXCursor Y) {
   return X.kind == Y.kind && X.data[0] == Y.data[0] && X.data[1] == Y.data[1] &&
          X.data[2] == Y.data[2];
diff --git a/tools/CIndex/CXCursor.h b/tools/CIndex/CXCursor.h
index 26bbc7d..ff474ed 100644
--- a/tools/CIndex/CXCursor.h
+++ b/tools/CIndex/CXCursor.h
@@ -50,11 +50,18 @@
 std::pair<ObjCProtocolDecl *, SourceLocation> 
   getCursorObjCProtocolRef(CXCursor C);
 
+/// \brief Create an Objective-C class reference at the given location.
+CXCursor MakeCursorObjCClassRef(ObjCInterfaceDecl *Class, SourceLocation Loc);
+
+/// \brief Unpack an ObjCClassRef cursor into the class it references
+/// and optionally the location where the reference occurred.
+std::pair<ObjCInterfaceDecl *, SourceLocation> 
+  getCursorObjCClassRef(CXCursor C);
+
 Decl *getCursorDecl(CXCursor Cursor);
 Expr *getCursorExpr(CXCursor Cursor);
 Stmt *getCursorStmt(CXCursor Cursor);
 Decl *getCursorReferringDecl(CXCursor Cursor);
-NamedDecl *getCursorInterfaceParent(CXCursor Cursor);
   
 bool operator==(CXCursor X, CXCursor Y);