From dd700becdd0dbf00a986b88d73e3aea74876135a Mon Sep 17 00:00:00 2001 From: John McCall Date: Mon, 16 Nov 2015 22:11:41 +0000 Subject: [PATCH] Correctly handle type mismatches in the __weak copy/move-initialization peephole I added in r250916. rdar://23559789 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@253255 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGDecl.cpp | 14 ++++++++++++-- test/CodeGenObjC/arc-weak.m | 20 ++++++++++++++++++++ test/CodeGenObjCXX/arc-weak.mm | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 test/CodeGenObjC/arc-weak.m create mode 100644 test/CodeGenObjCXX/arc-weak.mm diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index 35c7dfba06..b78e80d79d 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -600,12 +600,15 @@ static bool isAccessedBy(const ValueDecl *decl, const Expr *e) { static bool tryEmitARCCopyWeakInit(CodeGenFunction &CGF, const LValue &destLV, const Expr *init) { + bool needsCast = false; + while (auto castExpr = dyn_cast(init->IgnoreParens())) { switch (castExpr->getCastKind()) { // Look through casts that don't require representation changes. case CK_NoOp: case CK_BitCast: case CK_BlockPointerToObjCPointerCast: + needsCast = true; break; // If we find an l-value to r-value cast from a __weak variable, @@ -618,12 +621,19 @@ static bool tryEmitARCCopyWeakInit(CodeGenFunction &CGF, // Emit the source l-value. LValue srcLV = CGF.EmitLValue(srcExpr); + // Handle a formal type change to avoid asserting. + auto srcAddr = srcLV.getAddress(); + if (needsCast) { + srcAddr = CGF.Builder.CreateElementBitCast(srcAddr, + destLV.getAddress().getElementType()); + } + // If it was an l-value, use objc_copyWeak. if (srcExpr->getValueKind() == VK_LValue) { - CGF.EmitARCCopyWeak(destLV.getAddress(), srcLV.getAddress()); + CGF.EmitARCCopyWeak(destLV.getAddress(), srcAddr); } else { assert(srcExpr->getValueKind() == VK_XValue); - CGF.EmitARCMoveWeak(destLV.getAddress(), srcLV.getAddress()); + CGF.EmitARCMoveWeak(destLV.getAddress(), srcAddr); } return true; } diff --git a/test/CodeGenObjC/arc-weak.m b/test/CodeGenObjC/arc-weak.m new file mode 100644 index 0000000000..59f8d1d693 --- /dev/null +++ b/test/CodeGenObjC/arc-weak.m @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck %s + +__attribute((objc_root_class)) @interface A @end +@interface B : A @end + +// rdar://problem/23559789 +// Ensure that type differences don't cause an assert here. +void test0(__weak B **src) { + __weak A *dest = *src; +} +// CHECK-LABEL: define void @test0 +// CHECK: [[SRC:%.*]] = alloca [[B:%.*]]**, align 8 +// CHECK: [[DEST:%.*]] = alloca [[A:%.*]]*, align 8 +// CHECK: [[T0:%.*]] = load [[B]]**, [[B]]*** [[SRC]], align 8 +// CHECK-NEXT: [[T1:%.*]] = bitcast [[B]]** [[T0]] to [[A]]** +// CHECK-NEXT: [[T2:%.*]] = bitcast [[A]]** [[DEST]] to i8** +// CHECK-NEXT: [[T3:%.*]] = bitcast [[A]]** [[T1]] to i8** +// CHECK-NEXT: call void @objc_copyWeak(i8** [[T2]], i8** [[T3]]) +// CHECK-NEXT: [[T0:%.*]] = bitcast [[A]]** [[DEST]] to i8** +// CHECK: call void @objc_destroyWeak(i8** [[T0]]) diff --git a/test/CodeGenObjCXX/arc-weak.mm b/test/CodeGenObjCXX/arc-weak.mm new file mode 100644 index 0000000000..8fd03379aa --- /dev/null +++ b/test/CodeGenObjCXX/arc-weak.mm @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -std=c++11 -o - %s | FileCheck %s + +__attribute((objc_root_class)) @interface A @end +@interface B : A @end + +// rdar://problem/23559789 +// Ensure that type differences don't cause an assert here. +void test0(__weak B **src) { + __weak A *dest = *src; +} +// CHECK-LABEL: define void @_Z5test0PU6__weakP1B( +// CHECK: [[SRC:%.*]] = alloca [[B:%.*]]**, align 8 +// CHECK: [[DEST:%.*]] = alloca [[A:%.*]]*, align 8 +// CHECK: [[T0:%.*]] = load [[B]]**, [[B]]*** [[SRC]], align 8 +// CHECK-NEXT: [[T1:%.*]] = bitcast [[B]]** [[T0]] to [[A]]** +// CHECK-NEXT: [[T2:%.*]] = bitcast [[A]]** [[DEST]] to i8** +// CHECK-NEXT: [[T3:%.*]] = bitcast [[A]]** [[T1]] to i8** +// CHECK-NEXT: call void @objc_copyWeak(i8** [[T2]], i8** [[T3]]) +// CHECK-NEXT: [[T0:%.*]] = bitcast [[A]]** [[DEST]] to i8** +// CHECK: call void @objc_destroyWeak(i8** [[T0]]) + +void test1(__weak B **src) { + __weak A *dest = static_cast<__weak B*&&>(*src); +} +// CHECK-LABEL: define void @_Z5test1PU6__weakP1B( +// CHECK: [[SRC:%.*]] = alloca [[B:%.*]]**, align 8 +// CHECK: [[DEST:%.*]] = alloca [[A:%.*]]*, align 8 +// CHECK: [[T0:%.*]] = load [[B]]**, [[B]]*** [[SRC]], align 8 +// CHECK-NEXT: [[T1:%.*]] = bitcast [[B]]** [[T0]] to [[A]]** +// CHECK-NEXT: [[T2:%.*]] = bitcast [[A]]** [[DEST]] to i8** +// CHECK-NEXT: [[T3:%.*]] = bitcast [[A]]** [[T1]] to i8** +// CHECK-NEXT: call void @objc_moveWeak(i8** [[T2]], i8** [[T3]]) +// CHECK-NEXT: [[T0:%.*]] = bitcast [[A]]** [[DEST]] to i8** +// CHECK: call void @objc_destroyWeak(i8** [[T0]]) -- 2.40.0