Make the CIndex API more resilient to being used on invalid code.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@98981 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h
index de76076..6120c48 100644
--- a/include/clang-c/Index.h
+++ b/include/clang-c/Index.h
@@ -728,7 +728,8 @@
   CXCursor_InvalidFile                   = 70,
   CXCursor_NoDeclFound                   = 71,
   CXCursor_NotImplemented                = 72,
-  CXCursor_LastInvalid                   = 72,
+  CXCursor_InvalidCode                   = 73,
+  CXCursor_LastInvalid                   = CXCursor_InvalidCode,
 
   /* Expressions */
   CXCursor_FirstExpr                     = 100,
diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp
index 7d1033d..ab6b9e1 100644
--- a/lib/AST/DeclObjC.cpp
+++ b/lib/AST/DeclObjC.cpp
@@ -743,7 +743,10 @@
 }
 
 ObjCCategoryDecl *ObjCCategoryImplDecl::getCategoryDecl() const {
-  return getClassInterface()->FindCategoryDeclaration(getIdentifier());
+  // The class interface might be NULL if we are working with invalid code.
+  if (const ObjCInterfaceDecl *ID = getClassInterface())
+    return ID->FindCategoryDeclaration(getIdentifier());
+  return 0;
 }
 
 
diff --git a/tools/CIndex/CIndex.cpp b/tools/CIndex/CIndex.cpp
index f20bb75..b3c585a 100644
--- a/tools/CIndex/CIndex.cpp
+++ b/tools/CIndex/CIndex.cpp
@@ -621,9 +621,10 @@
 }
 
 bool CursorVisitor::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
-  if (Visit(MakeCursorObjCClassRef(D->getCategoryDecl()->getClassInterface(),
-                                   D->getLocation(), TU)))
-    return true;
+  // 'ID' could be null when dealing with invalid code.
+  if (ObjCInterfaceDecl *ID = D->getClassInterface())
+    if (Visit(MakeCursorObjCClassRef(ID, D->getLocation(), TU)))
+      return true;
 
   return VisitObjCImplDecl(D);
 }
diff --git a/tools/CIndex/CIndexUSRs.cpp b/tools/CIndex/CIndexUSRs.cpp
index 9dbbd35..8521971 100644
--- a/tools/CIndex/CIndexUSRs.cpp
+++ b/tools/CIndex/CIndexUSRs.cpp
@@ -155,14 +155,30 @@
       break;
     case Decl::ObjCCategory: {
       ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(D);
-      GenObjCCategory(CD->getClassInterface()->getName(),
-                      CD->getName());
+      ObjCInterfaceDecl *ID = CD->getClassInterface();
+      if (!ID) {
+        // Handle invalid code where the @interface might not
+        // have been specified.
+        // FIXME: We should be able to generate this USR even if the
+        // @interface isn't available.
+        IgnoreResults = true;
+        return;
+      }
+      GenObjCCategory(ID->getName(), CD->getName());
       break;
     }
     case Decl::ObjCCategoryImpl: {
       ObjCCategoryImplDecl *CD = cast<ObjCCategoryImplDecl>(D);
-      GenObjCCategory(CD->getClassInterface()->getName(),
-                      CD->getName());
+      ObjCInterfaceDecl *ID = CD->getClassInterface();
+      if (!ID) {
+        // Handle invalid code where the @interface might not
+        // have been specified.
+        // FIXME: We should be able to generate this USR even if the
+        // @interface isn't available.
+        IgnoreResults = true;
+        return;
+      }
+      GenObjCCategory(ID->getName(), CD->getName());
       break;
     }
     case Decl::ObjCProtocol:
@@ -251,7 +267,7 @@
   SUG->Visit(static_cast<Decl*>(D));
 
   if (SUG->ignoreResults() || SUG.str().empty())
-    return createCXString(NULL);
+    return createCXString("");
 
   // Return a copy of the string that must be disposed by the caller.
   return createCXString(SUG.str(), true);
diff --git a/tools/CIndex/CXCursor.cpp b/tools/CIndex/CXCursor.cpp
index 407f44c..cbf9d7e 100644
--- a/tools/CIndex/CXCursor.cpp
+++ b/tools/CIndex/CXCursor.cpp
@@ -266,7 +266,10 @@
 CXCursor cxcursor::MakeCursorObjCClassRef(ObjCInterfaceDecl *Class, 
                                           SourceLocation Loc, 
                                           ASTUnit *TU) {
-  assert(Class && TU && "Invalid arguments!");
+  // 'Class' can be null for invalid code.
+  if (!Class)
+    return MakeCXCursorInvalid(CXCursor_InvalidCode);
+  assert(TU && "Invalid arguments!");
   void *RawLoc = reinterpret_cast<void *>(Loc.getRawEncoding());
   CXCursor C = { CXCursor_ObjCClassRef, { Class, RawLoc, TU } };
   return C;