mirror of https://github.com/microsoft/clang.git
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 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@157641 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
6ea73b243b
commit
490a52b494
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]]
|
||||
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue