Correctly handle type mismatches in the __weak copy/move-initialization

peephole I added in r250916.

rdar://23559789

llvm-svn: 253255
This commit is contained in:
John McCall 2015-11-16 22:11:41 +00:00
parent 1bfc89baac
commit 0204e342ca
3 changed files with 66 additions and 2 deletions

View File

@ -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;
}

View File

@ -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]])

View File

@ -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]])