]> granicus.if.org Git - clang/commitdiff
Correctly handle type mismatches in the __weak copy/move-initialization
authorJohn McCall <rjmccall@apple.com>
Mon, 16 Nov 2015 22:11:41 +0000 (22:11 +0000)
committerJohn McCall <rjmccall@apple.com>
Mon, 16 Nov 2015 22:11:41 +0000 (22:11 +0000)
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
test/CodeGenObjC/arc-weak.m [new file with mode: 0644]
test/CodeGenObjCXX/arc-weak.mm [new file with mode: 0644]

index 35c7dfba064e7f7e81cb8e75e443b8f1cc9371b1..b78e80d79dddfc2e6cbca41c8fe37184a62735f1 100644 (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;
     }
diff --git a/test/CodeGenObjC/arc-weak.m b/test/CodeGenObjC/arc-weak.m
new file mode 100644 (file)
index 0000000..59f8d1d
--- /dev/null
@@ -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 (file)
index 0000000..8fd0337
--- /dev/null
@@ -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]])