objective-c: fix a sema and IRGen crash when property

getter result type is safe but does not match with property 
type resulting in spurious warning followed by crash in
IRGen. // rdar://11515196

llvm-svn: 157641
This commit is contained in:
Fariborz Jahanian 2012-05-29 19:56:01 +00:00
parent 76f6e2671a
commit b5dd2cb13c
5 changed files with 54 additions and 15 deletions

View File

@ -30,7 +30,7 @@ typedef llvm::PointerIntPair<llvm::Value*,1,bool> TryEmitResult;
static TryEmitResult
tryEmitARCRetainScalarExpr(CodeGenFunction &CGF, const Expr *e);
static RValue AdjustRelatedResultType(CodeGenFunction &CGF,
const Expr *E,
QualType ET,
const ObjCMethodDecl *Method,
RValue Result);
@ -202,20 +202,20 @@ llvm::Value *CodeGenFunction::EmitObjCProtocolExpr(const ObjCProtocolExpr *E) {
/// \brief Adjust the type of the result of an Objective-C message send
/// expression when the method has a related result type.
static RValue AdjustRelatedResultType(CodeGenFunction &CGF,
const Expr *E,
QualType ExpT,
const ObjCMethodDecl *Method,
RValue Result) {
if (!Method)
return Result;
if (!Method->hasRelatedResultType() ||
CGF.getContext().hasSameType(E->getType(), Method->getResultType()) ||
CGF.getContext().hasSameType(ExpT, Method->getResultType()) ||
!Result.isScalar())
return Result;
// We have applied a related result type. Cast the rvalue appropriately.
return RValue::get(CGF.Builder.CreateBitCast(Result.getScalarVal(),
CGF.ConvertType(E->getType())));
CGF.ConvertType(ExpT)));
}
/// Decide whether to extend the lifetime of the receiver of a
@ -401,7 +401,7 @@ RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E,
Builder.CreateStore(newSelf, selfAddr);
}
return AdjustRelatedResultType(*this, E, method, result);
return AdjustRelatedResultType(*this, E->getType(), method, result);
}
namespace {
@ -710,7 +710,7 @@ void CodeGenFunction::GenerateObjCGetter(ObjCImplementationDecl *IMP,
assert(OMD && "Invalid call to generate getter (empty method)");
StartObjCMethod(OMD, IMP->getClassInterface(), OMD->getLocStart());
generateObjCGetterBody(IMP, PID, AtomicHelperFn);
generateObjCGetterBody(IMP, PID, OMD, AtomicHelperFn);
FinishFunction();
}
@ -772,6 +772,7 @@ static void emitCPPObjectAtomicGetterCall(CodeGenFunction &CGF,
void
CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl,
const ObjCPropertyImplDecl *propImpl,
const ObjCMethodDecl *GetterMethodDecl,
llvm::Constant *AtomicHelperFn) {
// If there's a non-trivial 'get' expression, we just have to emit that.
if (!hasTrivialGetExpr(propImpl)) {
@ -905,6 +906,8 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl,
}
value = Builder.CreateBitCast(value, ConvertType(propType));
value = Builder.CreateBitCast(value,
ConvertType(GetterMethodDecl->getResultType()));
}
EmitReturnOfRValue(RValue::get(value), propType);

View File

@ -1310,6 +1310,7 @@ public:
const ObjCPropertyImplDecl *PID);
void generateObjCGetterBody(const ObjCImplementationDecl *classImpl,
const ObjCPropertyImplDecl *propImpl,
const ObjCMethodDecl *GetterMothodDecl,
llvm::Constant *AtomicHelperFn);
void GenerateObjCCtorDtorMethod(ObjCImplementationDecl *IMP,

View File

@ -1114,9 +1114,9 @@ bool Sema::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *property,
isa<ObjCObjectPointerType>(GetterType))
compat =
Context.canAssignObjCInterfaces(
PropertyIvarType->getAs<ObjCObjectPointerType>(),
GetterType->getAs<ObjCObjectPointerType>());
else if (CheckAssignmentConstraints(Loc, PropertyIvarType, GetterType)
GetterType->getAs<ObjCObjectPointerType>(),
PropertyIvarType->getAs<ObjCObjectPointerType>());
else if (CheckAssignmentConstraints(Loc, GetterType, PropertyIvarType)
!= Compatible) {
Diag(Loc, diag::error_property_accessor_type)
<< property->getDeclName() << PropertyIvarType

View File

@ -0,0 +1,35 @@
// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s
// rdar://11515196
@interface NSArray @end
@interface NSMutableArray : NSArray
- (void) addObject;
@end
@interface BPXLAppDelegate
- (NSArray *)arrayOfThings;
@end
@interface BPXLAppDelegate ()
@property (retain, nonatomic) NSMutableArray *arrayOfThings;
@end
@implementation BPXLAppDelegate
@synthesize arrayOfThings=_arrayOfThings;
- (void)applicationDidFinishLaunching
{
[self.arrayOfThings addObject];
}
@end
// CHECK: define internal [[RET:%.*]]* @"\01-[BPXLAppDelegate arrayOfThings
// CHECK: [[THREE:%.*]] = bitcast [[OPQ:%.*]]* [[TWO:%.*]] to [[RET]]*
// CHECK: ret [[RET]]* [[THREE]]

View File

@ -73,11 +73,11 @@ typedef void (F)(void);
NSArray* first;
}
@property (readonly) NSArray* pieces;
@property (readonly) NSMutableArray* first; // expected-warning {{type of property 'first' does not match type of accessor 'first'}}
@property (readonly) NSArray* pieces; // expected-warning {{type of property 'pieces' does not match type of accessor 'pieces'}}
@property (readonly) NSMutableArray* first;
- (NSMutableArray*) pieces;
- (NSArray*) first; // expected-note 2 {{declared here}}
- (NSMutableArray*) pieces; // expected-note 2 {{declared here}}
- (NSArray*) first;
@end
@interface Class2 {
@ -90,12 +90,12 @@ typedef void (F)(void);
- (id) lastPiece
{
return container.pieces;
return container.pieces; // expected-warning {{type of property 'pieces' does not match type of accessor 'pieces'}}
}
- (id)firstPeice
{
return container.first; // expected-warning {{type of property 'first' does not match type of accessor 'first'}}
return container.first;
}
@end