[ObjC] avoid crashing when emitting synthesized getter/setter and ptrdiff_t is smaller than long

On targets where ptrdiff_t is smaller than long, clang crashes when emitting
synthesized getters/setters that call objc_[gs]etProperty.  Explicitly emit a
zext/trunc of the ivar offset value (which is defined to long) to ptrdiff_t,
which objc_[gs]etProperty takes.

Add a test using the AVR target, where ptrdiff_t is smaller than long. Test
failed previously and passes now.

Differential Revision: https://reviews.llvm.org/D112049
This commit is contained in:
Matt Jacobson 2022-08-06 01:01:35 -04:00
parent 18df04c944
commit dd9f7963e4
4 changed files with 27 additions and 2 deletions

View File

@ -5242,6 +5242,15 @@ llvm::Value *CodeGenFunction::EmitIvarOffset(const ObjCInterfaceDecl *Interface,
return CGM.getObjCRuntime().EmitIvarOffset(*this, Interface, Ivar);
}
llvm::Value *
CodeGenFunction::EmitIvarOffsetAsPointerDiff(const ObjCInterfaceDecl *Interface,
const ObjCIvarDecl *Ivar) {
llvm::Value *OffsetValue = EmitIvarOffset(Interface, Ivar);
QualType PointerDiffType = getContext().getPointerDiffType();
return Builder.CreateZExtOrTrunc(OffsetValue,
getTypes().ConvertType(PointerDiffType));
}
LValue CodeGenFunction::EmitLValueForIvar(QualType ObjectTy,
llvm::Value *BaseValue,
const ObjCIvarDecl *Ivar,

View File

@ -1228,7 +1228,7 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl,
llvm::Value *cmd = emitCmdValueForGetterSetterBody(*this, getterMethod);
llvm::Value *self = Builder.CreateBitCast(LoadObjCSelf(), VoidPtrTy);
llvm::Value *ivarOffset =
EmitIvarOffset(classImpl->getClassInterface(), ivar);
EmitIvarOffsetAsPointerDiff(classImpl->getClassInterface(), ivar);
CallArgList args;
args.add(RValue::get(self), getContext().getObjCIdType());
@ -1532,7 +1532,7 @@ CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl,
llvm::Value *self =
Builder.CreateBitCast(LoadObjCSelf(), VoidPtrTy);
llvm::Value *ivarOffset =
EmitIvarOffset(classImpl->getClassInterface(), ivar);
EmitIvarOffsetAsPointerDiff(classImpl->getClassInterface(), ivar);
Address argAddr = GetAddrOfLocalVar(*setterMethod->param_begin());
llvm::Value *arg = Builder.CreateLoad(argAddr, "arg");
arg = Builder.CreateBitCast(arg, VoidPtrTy);

View File

@ -3974,6 +3974,8 @@ public:
llvm::Value *EmitIvarOffset(const ObjCInterfaceDecl *Interface,
const ObjCIvarDecl *Ivar);
llvm::Value *EmitIvarOffsetAsPointerDiff(const ObjCInterfaceDecl *Interface,
const ObjCIvarDecl *Ivar);
LValue EmitLValueForField(LValue Base, const FieldDecl* Field);
LValue EmitLValueForLambdaField(const FieldDecl *Field);

View File

@ -0,0 +1,14 @@
// RUN: %clang_cc1 -triple avr -emit-llvm -fobjc-runtime=macosx %s -o /dev/null
__attribute__((objc_root_class))
@interface Foo
@property(strong) Foo *f;
@end
@implementation Foo
@synthesize f = _f;
@end