CXCursor_InvalidFile = 70,
CXCursor_NoDeclFound = 71,
CXCursor_NotImplemented = 72,
- CXCursor_LastInvalid = 72,
+ CXCursor_InvalidCode = 73,
+ CXCursor_LastInvalid = CXCursor_InvalidCode,
/* Expressions */
CXCursor_FirstExpr = 100,
}
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;
}
}
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);
}
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:
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);
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;