1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
|
// RUN: %clang_cc1 -triple arm64-apple-ios9 -fobjc-runtime=ios-9.0 -fobjc-arc -O -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK
// RUN: %clang_cc1 -triple x86_64-apple-macosx10 -fobjc-runtime=ios-9.0 -fobjc-arc -O -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK
@class A;
A *makeA(void);
void test_assign(void) {
__unsafe_unretained id x;
x = makeA();
}
// CHECK-LABEL: define{{.*}} void @test_assign()
// CHECK: [[X:%.*]] = alloca ptr
// CHECK: [[T0:%.*]] = call ptr @makeA() [ "clang.arc.attachedcall"(ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
// CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use({{.*}} [[T0]])
// CHECK-NEXT: store ptr [[T0]], ptr [[X]]
// CHECK-NEXT: lifetime.end
// CHECK-NEXT: ret void
void test_assign_assign(void) {
__unsafe_unretained id x, y;
x = y = makeA();
}
// CHECK-LABEL: define{{.*}} void @test_assign_assign()
// CHECK: [[X:%.*]] = alloca ptr
// CHECK: [[Y:%.*]] = alloca ptr
// CHECK: [[T0:%.*]] = call ptr @makeA() [ "clang.arc.attachedcall"(ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
// CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use({{.*}} [[T0]])
// CHECK-NEXT: store ptr [[T0]], ptr [[Y]]
// CHECK-NEXT: store ptr [[T0]], ptr [[X]]
// CHECK-NEXT: lifetime.end
// CHECK-NEXT: lifetime.end
// CHECK-NEXT: ret void
void test_strong_assign_assign(void) {
__strong id x;
__unsafe_unretained id y;
x = y = makeA();
}
// CHECK-LABEL: define{{.*}} void @test_strong_assign_assign()
// CHECK: [[X:%.*]] = alloca ptr
// CHECK: [[Y:%.*]] = alloca ptr
// CHECK: [[T0:%.*]] = call ptr @makeA() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
// CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use({{.*}} [[T0]])
// CHECK-NEXT: store ptr [[T0]], ptr [[Y]]
// CHECK-NEXT: [[OLD:%.*]] = load ptr, ptr [[X]]
// CHECK-NEXT: store ptr [[T0]], ptr [[X]]
// CHECK-NEXT: call void @llvm.objc.release(ptr [[OLD]]
// CHECK-NEXT: lifetime.end
// CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[X]]
// CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]])
// CHECK-NEXT: lifetime.end
// CHECK-NEXT: ret void
void test_assign_strong_assign(void) {
__unsafe_unretained id x;
__strong id y;
x = y = makeA();
}
// CHECK-LABEL: define{{.*}} void @test_assign_strong_assign()
// CHECK: [[X:%.*]] = alloca ptr
// CHECK: [[Y:%.*]] = alloca ptr
// CHECK: [[T0:%.*]] = call ptr @makeA() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
// CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use({{.*}} [[T0]])
// CHECK-NEXT: [[OLD:%.*]] = load ptr, ptr [[Y]]
// CHECK-NEXT: store ptr [[T0]], ptr [[Y]]
// CHECK-NEXT: call void @llvm.objc.release(ptr [[OLD]]
// CHECK-NEXT: store ptr [[T0]], ptr [[X]]
// CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[Y]]
// CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]])
// CHECK-NEXT: lifetime.end
// CHECK-NEXT: lifetime.end
// CHECK-NEXT: ret void
void test_init(void) {
__unsafe_unretained id x = makeA();
}
// CHECK-LABEL: define{{.*}} void @test_init()
// CHECK: [[X:%.*]] = alloca ptr
// CHECK: [[T0:%.*]] = call ptr @makeA() [ "clang.arc.attachedcall"(ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
// CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use({{.*}} [[T0]])
// CHECK-NEXT: store ptr [[T0]], ptr [[X]]
// CHECK-NEXT: lifetime.end
// CHECK-NEXT: ret void
void test_init_assignment(void) {
__unsafe_unretained id x;
__unsafe_unretained id y = x = makeA();
}
// CHECK-LABEL: define{{.*}} void @test_init_assignment()
// CHECK: [[X:%.*]] = alloca ptr
// CHECK: [[Y:%.*]] = alloca ptr
// CHECK: [[T0:%.*]] = call ptr @makeA() [ "clang.arc.attachedcall"(ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
// CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use({{.*}} [[T0]])
// CHECK-NEXT: store ptr [[T0]], ptr [[X]]
// CHECK-NEXT: store ptr [[T0]], ptr [[Y]]
// CHECK-NEXT: lifetime.end
// CHECK-NEXT: lifetime.end
// CHECK-NEXT: ret void
void test_strong_init_assignment(void) {
__unsafe_unretained id x;
__strong id y = x = makeA();
}
// CHECK-LABEL: define{{.*}} void @test_strong_init_assignment()
// CHECK: [[X:%.*]] = alloca ptr
// CHECK: [[Y:%.*]] = alloca ptr
// CHECK: [[T0:%.*]] = call ptr @makeA() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
// CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use({{.*}} [[T0]])
// CHECK-NEXT: store ptr [[T0]], ptr [[X]]
// CHECK-NEXT: store ptr [[T0]], ptr [[Y]]
// CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[Y]]
// CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]])
// CHECK-NEXT: lifetime.end
// CHECK-NEXT: lifetime.end
// CHECK-NEXT: ret void
void test_init_strong_assignment(void) {
__strong id x;
__unsafe_unretained id y = x = makeA();
}
// CHECK-LABEL: define{{.*}} void @test_init_strong_assignment()
// CHECK: [[X:%.*]] = alloca ptr
// CHECK: [[Y:%.*]] = alloca ptr
// CHECK: [[T0:%.*]] = call ptr @makeA() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
// CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use({{.*}} [[T0]])
// CHECK-NEXT: [[OLD:%.*]] = load ptr, ptr [[X]]
// CHECK-NEXT: store ptr [[T0]], ptr [[X]]
// CHECK-NEXT: call void @llvm.objc.release(ptr [[OLD]])
// CHECK-NEXT: store ptr [[T0]], ptr [[Y]]
// CHECK-NEXT: lifetime.end
// CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[X]]
// CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]])
// CHECK-NEXT: lifetime.end
// CHECK-NEXT: ret void
void test_ignored(void) {
makeA();
}
// CHECK-LABEL: define{{.*}} void @test_ignored()
// CHECK: [[T0:%.*]] = call ptr @makeA() [ "clang.arc.attachedcall"(ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
// CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use({{.*}} [[T0]])
// CHECK-NEXT: ret void
void test_cast_to_void(void) {
(void) makeA();
}
// CHECK-LABEL: define{{.*}} void @test_cast_to_void()
// CHECK: [[T0:%.*]] = call ptr @makeA() [ "clang.arc.attachedcall"(ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
// CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use({{.*}} [[T0]])
// CHECK-NEXT: ret void
// This is always at the end of the module.
// CHECK-OPTIMIZED: !llvm.module.flags = !{!0,
// CHECK-OPTIMIZED: !0 = !{i32 1, !"clang.arc.retainAutoreleasedReturnValueMarker", !"mov{{.*}}marker for objc_retainAutoreleaseReturnValue"}
|