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;