diff options
-rw-r--r-- | clang/lib/CodeGen/CGDecl.cpp | 14 | ||||
-rw-r--r-- | clang/test/CodeGenObjC/arc-weak.m | 20 | ||||
-rw-r--r-- | clang/test/CodeGenObjCXX/arc-weak.mm | 34 |
3 files changed, 66 insertions, 2 deletions
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index 35c7dfba064..b78e80d79dd 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/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<CastExpr>(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/clang/test/CodeGenObjC/arc-weak.m b/clang/test/CodeGenObjC/arc-weak.m new file mode 100644 index 00000000000..59f8d1d6930 --- /dev/null +++ b/clang/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/clang/test/CodeGenObjCXX/arc-weak.mm b/clang/test/CodeGenObjCXX/arc-weak.mm new file mode 100644 index 00000000000..8fd03379aa6 --- /dev/null +++ b/clang/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]]) |