diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-05-27 01:19:52 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-05-27 01:19:52 +0000 |
commit | f968d8374791c37bc464efd9168c2d33dd73605f (patch) | |
tree | 75ddf1b9df53d9bde10c6dbc8e48fa9c4faa7239 /lib/CodeGen | |
parent | 9910df05e9b5f03043f4d8dc12ea1bbb722664df (diff) |
Objective-C doesn't consider the use of incomplete types as method
parameter types to be ill-formed. However, it relies on the
completeness of method parameter types when producing metadata, e.g.,
for a protocol, leading IR generating to crash in such cases.
Since there's no real way to tighten down the semantics of Objective-C
here without breaking existing code, do something safe but lame:
suppress the generation of metadata when this happens.
Fixes <rdar://problem/9123036>.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@132171 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/CGObjCMac.cpp | 25 |
1 files changed, 23 insertions, 2 deletions
diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index 99d464f884..520d94e1bb 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -1686,6 +1686,7 @@ void CGObjCCommonMac::GenerateProtocol(const ObjCProtocolDecl *PD) { llvm::Constant *CGObjCCommonMac::GetProtocolRef(const ObjCProtocolDecl *PD) { if (DefinedProtocols.count(PD->getIdentifier())) return GetOrEmitProtocol(PD); + return GetOrEmitProtocolRef(PD); } @@ -1719,6 +1720,9 @@ llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) { i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) { ObjCMethodDecl *MD = *i; llvm::Constant *C = GetMethodDescriptionConstant(MD); + if (!C) + return GetOrEmitProtocolRef(PD); + if (MD->getImplementationControl() == ObjCMethodDecl::Optional) { OptInstanceMethods.push_back(C); } else { @@ -1730,6 +1734,9 @@ llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) { i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) { ObjCMethodDecl *MD = *i; llvm::Constant *C = GetMethodDescriptionConstant(MD); + if (!C) + return GetOrEmitProtocolRef(PD); + if (MD->getImplementationControl() == ObjCMethodDecl::Optional) { OptClassMethods.push_back(C); } else { @@ -1973,6 +1980,9 @@ CGObjCMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) { llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()), ObjCTypes.SelectorPtrTy); Desc[1] = GetMethodVarType(MD); + if (!Desc[1]) + return 0; + return llvm::ConstantStruct::get(ObjCTypes.MethodDescriptionTy, Desc); } @@ -3935,8 +3945,10 @@ llvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) { llvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D) { std::string TypeStr; - CGM.getContext().getObjCEncodingForMethodDecl(const_cast<ObjCMethodDecl*>(D), - TypeStr); + if (CGM.getContext().getObjCEncodingForMethodDecl( + const_cast<ObjCMethodDecl*>(D), + TypeStr)) + return 0; llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr]; @@ -5359,6 +5371,9 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol( i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) { ObjCMethodDecl *MD = *i; llvm::Constant *C = GetMethodDescriptionConstant(MD); + if (!C) + return GetOrEmitProtocolRef(PD); + if (MD->getImplementationControl() == ObjCMethodDecl::Optional) { OptInstanceMethods.push_back(C); } else { @@ -5370,6 +5385,9 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol( i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) { ObjCMethodDecl *MD = *i; llvm::Constant *C = GetMethodDescriptionConstant(MD); + if (!C) + return GetOrEmitProtocolRef(PD); + if (MD->getImplementationControl() == ObjCMethodDecl::Optional) { OptClassMethods.push_back(C); } else { @@ -5509,6 +5527,9 @@ CGObjCNonFragileABIMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) { llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()), ObjCTypes.SelectorPtrTy); Desc[1] = GetMethodVarType(MD); + if (!Desc[1]) + return 0; + // Protocol methods have no implementation. So, this entry is always NULL. Desc[2] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy); return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Desc); |