[ObjC] avoid crashing when emitting synthesized getter/setter and ptrdiff_t is smalle...
authorMatt Jacobson <mhjacobson@me.com>
Sat, 6 Aug 2022 05:01:35 +0000 (01:01 -0400)
committerMatt Jacobson <mhjacobson@me.com>
Thu, 10 Nov 2022 07:10:30 +0000 (02:10 -0500)
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

clang/lib/CodeGen/CGExpr.cpp
clang/lib/CodeGen/CGObjC.cpp
clang/lib/CodeGen/CodeGenFunction.h
clang/test/CodeGen/avr/objc-property.m [new file with mode: 0644]

index 40d9b8f..ee09a85 100644 (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,
index 5ec2fdb..3eb530d 100644 (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);
index 05e5bad..7ef22eb 100644 (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);
 
diff --git a/clang/test/CodeGen/avr/objc-property.m b/clang/test/CodeGen/avr/objc-property.m
new file mode 100644 (file)
index 0000000..a3eaea2
--- /dev/null
@@ -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