xref: /minix3/external/bsd/llvm/dist/clang/test/CodeGenObjC/arc-blocks.m (revision f4a2713ac843a11c696ec80c0a5e3e5d80b4d338)
1*f4a2713aSLionel Sambuc// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -O2 -disable-llvm-optzns -o - %s | FileCheck %s
2*f4a2713aSLionel Sambuc// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=CHECK-UNOPT %s
3*f4a2713aSLionel Sambuc
4*f4a2713aSLionel Sambuc// This shouldn't crash.
5*f4a2713aSLionel Sambucvoid test0(id (^maker)(void)) {
6*f4a2713aSLionel Sambuc  maker();
7*f4a2713aSLionel Sambuc}
8*f4a2713aSLionel Sambuc
9*f4a2713aSLionel Sambucint (^test1(int x))(void) {
10*f4a2713aSLionel Sambuc  // CHECK-LABEL:    define i32 ()* @test1(
11*f4a2713aSLionel Sambuc  // CHECK:      [[X:%.*]] = alloca i32,
12*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
13*f4a2713aSLionel Sambuc  // CHECK-NEXT: store i32 {{%.*}}, i32* [[X]]
14*f4a2713aSLionel Sambuc  // CHECK:      [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to i32 ()*
15*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T1:%.*]] = bitcast i32 ()* [[T0]] to i8*
16*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]]) [[NUW:#[0-9]+]]
17*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to i32 ()*
18*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T4:%.*]] = bitcast i32 ()* [[T3]] to i8*
19*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T5:%.*]] = tail call i8* @objc_autoreleaseReturnValue(i8* [[T4]]) [[NUW]]
20*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T6:%.*]] = bitcast i8* [[T5]] to i32 ()*
21*f4a2713aSLionel Sambuc  // CHECK-NEXT: ret i32 ()* [[T6]]
22*f4a2713aSLionel Sambuc  return ^{ return x; };
23*f4a2713aSLionel Sambuc}
24*f4a2713aSLionel Sambuc
25*f4a2713aSLionel Sambucvoid test2(id x) {
26*f4a2713aSLionel Sambuc// CHECK-LABEL:    define void @test2(
27*f4a2713aSLionel Sambuc// CHECK:      [[X:%.*]] = alloca i8*,
28*f4a2713aSLionel Sambuc// CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
29*f4a2713aSLionel Sambuc// CHECK-NEXT: [[PARM:%.*]] = call i8* @objc_retain(i8* {{%.*}})
30*f4a2713aSLionel Sambuc// CHECK-NEXT: store i8* [[PARM]], i8** [[X]]
31*f4a2713aSLionel Sambuc// CHECK-NEXT: [[SLOTREL:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
32*f4a2713aSLionel Sambuc// CHECK:      [[SLOT:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
33*f4a2713aSLionel Sambuc// CHECK-NEXT: [[T0:%.*]] = load i8** [[X]],
34*f4a2713aSLionel Sambuc// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]])
35*f4a2713aSLionel Sambuc// CHECK-NEXT: store i8* [[T1]], i8** [[SLOT]],
36*f4a2713aSLionel Sambuc// CHECK-NEXT: bitcast
37*f4a2713aSLionel Sambuc// CHECK-NEXT: call void @test2_helper(
38*f4a2713aSLionel Sambuc// CHECK-NEXT: [[T0:%.*]] = load i8** [[SLOTREL]]
39*f4a2713aSLionel Sambuc// CHECK-NEXT: call void @objc_release(i8* [[T0]]) [[NUW]], !clang.imprecise_release
40*f4a2713aSLionel Sambuc// CHECK-NEXT: [[T0:%.*]] = load i8** [[X]]
41*f4a2713aSLionel Sambuc// CHECK-NEXT: call void @objc_release(i8* [[T0]]) [[NUW]], !clang.imprecise_release
42*f4a2713aSLionel Sambuc// CHECK-NEXT: ret void
43*f4a2713aSLionel Sambuc  extern void test2_helper(id (^)(void));
44*f4a2713aSLionel Sambuc  test2_helper(^{ return x; });
45*f4a2713aSLionel Sambuc
46*f4a2713aSLionel Sambuc// CHECK-LABEL:    define internal void @__copy_helper_block_
47*f4a2713aSLionel Sambuc// CHECK:      [[T0:%.*]] = load i8**
48*f4a2713aSLionel Sambuc// CHECK-NEXT: [[SRC:%.*]] = bitcast i8* [[T0]] to [[BLOCK_T]]*
49*f4a2713aSLionel Sambuc// CHECK-NEXT: [[T0:%.*]] = load i8**
50*f4a2713aSLionel Sambuc// CHECK-NEXT: [[DST:%.*]] = bitcast i8* [[T0]] to [[BLOCK_T]]*
51*f4a2713aSLionel Sambuc// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[SRC]], i32 0, i32 5
52*f4a2713aSLionel Sambuc// CHECK-NEXT: [[T1:%.*]] = load i8** [[T0]]
53*f4a2713aSLionel Sambuc// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]]) [[NUW]]
54*f4a2713aSLionel Sambuc// CHECK-NEXT: ret void
55*f4a2713aSLionel Sambuc
56*f4a2713aSLionel Sambuc// CHECK-LABEL:    define internal void @__destroy_helper_block_
57*f4a2713aSLionel Sambuc// CHECK:      [[T0:%.*]] = load i8**
58*f4a2713aSLionel Sambuc// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[BLOCK_T]]*
59*f4a2713aSLionel Sambuc// CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[T1]], i32 0, i32 5
60*f4a2713aSLionel Sambuc// CHECK-NEXT: [[T3:%.*]] = load i8** [[T2]]
61*f4a2713aSLionel Sambuc// CHECK-NEXT: call void @objc_release(i8* [[T3]])
62*f4a2713aSLionel Sambuc// CHECK-NEXT: ret void
63*f4a2713aSLionel Sambuc}
64*f4a2713aSLionel Sambuc
65*f4a2713aSLionel Sambucvoid test3(void (^sink)(id*)) {
66*f4a2713aSLionel Sambuc  __strong id strong;
67*f4a2713aSLionel Sambuc  sink(&strong);
68*f4a2713aSLionel Sambuc
69*f4a2713aSLionel Sambuc  // CHECK-LABEL:    define void @test3(
70*f4a2713aSLionel Sambuc  // CHECK:      [[SINK:%.*]] = alloca void (i8**)*
71*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[STRONG:%.*]] = alloca i8*
72*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[TEMP:%.*]] = alloca i8*
73*f4a2713aSLionel Sambuc  // CHECK-NEXT: bitcast void (i8**)* {{%.*}} to i8*
74*f4a2713aSLionel Sambuc  // CHECK-NEXT: call i8* @objc_retain(
75*f4a2713aSLionel Sambuc  // CHECK-NEXT: bitcast i8*
76*f4a2713aSLionel Sambuc  // CHECK-NEXT: store void (i8**)* {{%.*}}, void (i8**)** [[SINK]]
77*f4a2713aSLionel Sambuc  // CHECK-NEXT: store i8* null, i8** [[STRONG]]
78*f4a2713aSLionel Sambuc
79*f4a2713aSLionel Sambuc  // CHECK-NEXT: load void (i8**)** [[SINK]]
80*f4a2713aSLionel Sambuc  // CHECK-NEXT: bitcast
81*f4a2713aSLionel Sambuc  // CHECK-NEXT: getelementptr
82*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[BLOCK:%.*]] = bitcast
83*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[V:%.*]] = load i8** [[STRONG]]
84*f4a2713aSLionel Sambuc  // CHECK-NEXT: store i8* [[V]], i8** [[TEMP]]
85*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[F0:%.*]] = load i8**
86*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[F1:%.*]] = bitcast i8* [[F0]] to void (i8*, i8**)*
87*f4a2713aSLionel Sambuc  // CHECK-NEXT: call void [[F1]](i8* [[BLOCK]], i8** [[TEMP]])
88*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T0:%.*]] = load i8** [[TEMP]]
89*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]])
90*f4a2713aSLionel Sambuc  // CHECK-NEXT: call void (...)* @clang.arc.use(i8* [[V]]) [[NUW]]
91*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T2:%.*]] = load i8** [[STRONG]]
92*f4a2713aSLionel Sambuc  // CHECK-NEXT: store i8* [[T1]], i8** [[STRONG]]
93*f4a2713aSLionel Sambuc  // CHECK-NEXT: call void @objc_release(i8* [[T2]])
94*f4a2713aSLionel Sambuc
95*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T0:%.*]] = load i8** [[STRONG]]
96*f4a2713aSLionel Sambuc  // CHECK-NEXT: call void @objc_release(i8* [[T0]])
97*f4a2713aSLionel Sambuc
98*f4a2713aSLionel Sambuc  // CHECK-NEXT: load void (i8**)** [[SINK]]
99*f4a2713aSLionel Sambuc  // CHECK-NEXT: bitcast
100*f4a2713aSLionel Sambuc  // CHECK-NEXT: call void @objc_release
101*f4a2713aSLionel Sambuc  // CHECK-NEXT: ret void
102*f4a2713aSLionel Sambuc
103*f4a2713aSLionel Sambuc}
104*f4a2713aSLionel Sambuc
105*f4a2713aSLionel Sambucvoid test4(void) {
106*f4a2713aSLionel Sambuc  id test4_source(void);
107*f4a2713aSLionel Sambuc  void test4_helper(void (^)(void));
108*f4a2713aSLionel Sambuc  __block id var = test4_source();
109*f4a2713aSLionel Sambuc  test4_helper(^{ var = 0; });
110*f4a2713aSLionel Sambuc
111*f4a2713aSLionel Sambuc  // CHECK-LABEL:    define void @test4()
112*f4a2713aSLionel Sambuc  // CHECK:      [[VAR:%.*]] = alloca [[BYREF_T:%.*]],
113*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
114*f4a2713aSLionel Sambuc  // CHECK:      [[T0:%.*]] = getelementptr inbounds [[BYREF_T]]* [[VAR]], i32 0, i32 2
115*f4a2713aSLionel Sambuc  // 0x02000000 - has copy/dispose helpers strong
116*f4a2713aSLionel Sambuc  // CHECK-NEXT: store i32 838860800, i32* [[T0]]
117*f4a2713aSLionel Sambuc  // CHECK:      [[SLOT:%.*]] = getelementptr inbounds [[BYREF_T]]* [[VAR]], i32 0, i32 6
118*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T0:%.*]] = call i8* @test4_source()
119*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
120*f4a2713aSLionel Sambuc  // CHECK-NEXT: store i8* [[T1]], i8** [[SLOT]]
121*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[SLOT:%.*]] = getelementptr inbounds [[BYREF_T]]* [[VAR]], i32 0, i32 6
122*f4a2713aSLionel Sambuc  // 0x42800000 - has signature, copy/dispose helpers, as well as BLOCK_HAS_EXTENDED_LAYOUT
123*f4a2713aSLionel Sambuc  // CHECK:      store i32 -1040187392,
124*f4a2713aSLionel Sambuc  // CHECK:      [[T0:%.*]] = bitcast [[BYREF_T]]* [[VAR]] to i8*
125*f4a2713aSLionel Sambuc  // CHECK-NEXT: store i8* [[T0]], i8**
126*f4a2713aSLionel Sambuc  // CHECK:      call void @test4_helper(
127*f4a2713aSLionel Sambuc  // CHECK:      [[T0:%.*]] = bitcast [[BYREF_T]]* [[VAR]] to i8*
128*f4a2713aSLionel Sambuc  // CHECK-NEXT: call void @_Block_object_dispose(i8* [[T0]], i32 8)
129*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T0:%.*]] = load i8** [[SLOT]]
130*f4a2713aSLionel Sambuc  // CHECK-NEXT: call void @objc_release(i8* [[T0]])
131*f4a2713aSLionel Sambuc  // CHECK: ret void
132*f4a2713aSLionel Sambuc
133*f4a2713aSLionel Sambuc  // CHECK-LABEL:    define internal void @__Block_byref_object_copy_
134*f4a2713aSLionel Sambuc  // CHECK:      [[T0:%.*]] = getelementptr inbounds [[BYREF_T]]* {{%.*}}, i32 0, i32 6
135*f4a2713aSLionel Sambuc  // CHECK-NEXT: load i8**
136*f4a2713aSLionel Sambuc  // CHECK-NEXT: bitcast i8* {{%.*}} to [[BYREF_T]]*
137*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[BYREF_T]]* {{%.*}}, i32 0, i32 6
138*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T2:%.*]] = load i8** [[T1]]
139*f4a2713aSLionel Sambuc  // CHECK-NEXT: store i8* [[T2]], i8** [[T0]]
140*f4a2713aSLionel Sambuc  // CHECK-NEXT: store i8* null, i8** [[T1]]
141*f4a2713aSLionel Sambuc
142*f4a2713aSLionel Sambuc  // CHECK-LABEL:    define internal void @__Block_byref_object_dispose_
143*f4a2713aSLionel Sambuc  // CHECK:      [[T0:%.*]] = getelementptr inbounds [[BYREF_T]]* {{%.*}}, i32 0, i32 6
144*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T1:%.*]] = load i8** [[T0]]
145*f4a2713aSLionel Sambuc  // CHECK-NEXT: call void @objc_release(i8* [[T1]])
146*f4a2713aSLionel Sambuc
147*f4a2713aSLionel Sambuc  // CHECK-LABEL:    define internal void @__test4_block_invoke
148*f4a2713aSLionel Sambuc  // CHECK:      [[SLOT:%.*]] = getelementptr inbounds {{.*}}, i32 0, i32 6
149*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T0:%.*]] = load i8** [[SLOT]], align 8
150*f4a2713aSLionel Sambuc  // CHECK-NEXT: store i8* null, i8** [[SLOT]],
151*f4a2713aSLionel Sambuc  // CHECK-NEXT: call void @objc_release(i8* [[T0]])
152*f4a2713aSLionel Sambuc  // CHECK-NEXT: ret void
153*f4a2713aSLionel Sambuc
154*f4a2713aSLionel Sambuc  // CHECK-LABEL:    define internal void @__copy_helper_block_
155*f4a2713aSLionel Sambuc  // CHECK:      call void @_Block_object_assign(i8* {{%.*}}, i8* {{%.*}}, i32 8)
156*f4a2713aSLionel Sambuc
157*f4a2713aSLionel Sambuc  // CHECK-LABEL:    define internal void @__destroy_helper_block_
158*f4a2713aSLionel Sambuc  // CHECK:      call void @_Block_object_dispose(i8* {{%.*}}, i32 8)
159*f4a2713aSLionel Sambuc}
160*f4a2713aSLionel Sambuc
161*f4a2713aSLionel Sambucvoid test5(void) {
162*f4a2713aSLionel Sambuc  extern id test5_source(void);
163*f4a2713aSLionel Sambuc  void test5_helper(void (^)(void));
164*f4a2713aSLionel Sambuc  __unsafe_unretained id var = test5_source();
165*f4a2713aSLionel Sambuc  test5_helper(^{ (void) var; });
166*f4a2713aSLionel Sambuc
167*f4a2713aSLionel Sambuc  // CHECK-LABEL:    define void @test5()
168*f4a2713aSLionel Sambuc  // CHECK:      [[VAR:%.*]] = alloca i8*
169*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
170*f4a2713aSLionel Sambuc  // CHECK: [[T0:%.*]] = call i8* @test5_source()
171*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
172*f4a2713aSLionel Sambuc  // CHECK-NEXT: store i8* [[T1]], i8** [[VAR]],
173*f4a2713aSLionel Sambuc  // CHECK-NEXT: call void @objc_release(i8* [[T1]])
174*f4a2713aSLionel Sambuc  // 0x40800000 - has signature but no copy/dispose, as well as BLOCK_HAS_EXTENDED_LAYOUT
175*f4a2713aSLionel Sambuc  // CHECK:      store i32 -1073741824, i32*
176*f4a2713aSLionel Sambuc  // CHECK:      [[CAPTURE:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
177*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T0:%.*]] = load i8** [[VAR]]
178*f4a2713aSLionel Sambuc  // CHECK-NEXT: store i8* [[T0]], i8** [[CAPTURE]]
179*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to
180*f4a2713aSLionel Sambuc  // CHECK: call void @test5_helper
181*f4a2713aSLionel Sambuc  // CHECK-NEXT: ret void
182*f4a2713aSLionel Sambuc}
183*f4a2713aSLionel Sambuc
184*f4a2713aSLionel Sambucvoid test6(void) {
185*f4a2713aSLionel Sambuc  id test6_source(void);
186*f4a2713aSLionel Sambuc  void test6_helper(void (^)(void));
187*f4a2713aSLionel Sambuc  __block __weak id var = test6_source();
188*f4a2713aSLionel Sambuc  test6_helper(^{ var = 0; });
189*f4a2713aSLionel Sambuc
190*f4a2713aSLionel Sambuc  // CHECK-LABEL:    define void @test6()
191*f4a2713aSLionel Sambuc  // CHECK:      [[VAR:%.*]] = alloca [[BYREF_T:%.*]],
192*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
193*f4a2713aSLionel Sambuc  // CHECK:      [[T0:%.*]] = getelementptr inbounds [[BYREF_T]]* [[VAR]], i32 0, i32 2
194*f4a2713aSLionel Sambuc  // 0x02000000 - has copy/dispose helpers weak
195*f4a2713aSLionel Sambuc  // CHECK-NEXT: store i32 1107296256, i32* [[T0]]
196*f4a2713aSLionel Sambuc  // CHECK:      [[SLOT:%.*]] = getelementptr inbounds [[BYREF_T]]* [[VAR]], i32 0, i32 6
197*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T0:%.*]] = call i8* @test6_source()
198*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
199*f4a2713aSLionel Sambuc  // CHECK-NEXT: call i8* @objc_initWeak(i8** [[SLOT]], i8* [[T1]])
200*f4a2713aSLionel Sambuc  // CHECK-NEXT: call void @objc_release(i8* [[T1]])
201*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[SLOT:%.*]] = getelementptr inbounds [[BYREF_T]]* [[VAR]], i32 0, i32 6
202*f4a2713aSLionel Sambuc  // 0x42800000 - has signature, copy/dispose helpers, as well as BLOCK_HAS_EXTENDED_LAYOUT
203*f4a2713aSLionel Sambuc  // CHECK:      store i32 -1040187392,
204*f4a2713aSLionel Sambuc  // CHECK:      [[T0:%.*]] = bitcast [[BYREF_T]]* [[VAR]] to i8*
205*f4a2713aSLionel Sambuc  // CHECK-NEXT: store i8* [[T0]], i8**
206*f4a2713aSLionel Sambuc  // CHECK:      call void @test6_helper(
207*f4a2713aSLionel Sambuc  // CHECK:      [[T0:%.*]] = bitcast [[BYREF_T]]* [[VAR]] to i8*
208*f4a2713aSLionel Sambuc  // CHECK-NEXT: call void @_Block_object_dispose(i8* [[T0]], i32 8)
209*f4a2713aSLionel Sambuc  // CHECK-NEXT: call void @objc_destroyWeak(i8** [[SLOT]])
210*f4a2713aSLionel Sambuc  // CHECK: ret void
211*f4a2713aSLionel Sambuc
212*f4a2713aSLionel Sambuc  // CHECK-LABEL:    define internal void @__Block_byref_object_copy_
213*f4a2713aSLionel Sambuc  // CHECK:      [[T0:%.*]] = getelementptr inbounds [[BYREF_T]]* {{%.*}}, i32 0, i32 6
214*f4a2713aSLionel Sambuc  // CHECK-NEXT: load i8**
215*f4a2713aSLionel Sambuc  // CHECK-NEXT: bitcast i8* {{%.*}} to [[BYREF_T]]*
216*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[BYREF_T]]* {{%.*}}, i32 0, i32 6
217*f4a2713aSLionel Sambuc  // CHECK-NEXT: call void @objc_moveWeak(i8** [[T0]], i8** [[T1]])
218*f4a2713aSLionel Sambuc
219*f4a2713aSLionel Sambuc  // CHECK-LABEL:    define internal void @__Block_byref_object_dispose_
220*f4a2713aSLionel Sambuc  // CHECK:      [[T0:%.*]] = getelementptr inbounds [[BYREF_T]]* {{%.*}}, i32 0, i32 6
221*f4a2713aSLionel Sambuc  // CHECK-NEXT: call void @objc_destroyWeak(i8** [[T0]])
222*f4a2713aSLionel Sambuc
223*f4a2713aSLionel Sambuc  // CHECK-LABEL:    define internal void @__test6_block_invoke
224*f4a2713aSLionel Sambuc  // CHECK:      [[SLOT:%.*]] = getelementptr inbounds {{.*}}, i32 0, i32 6
225*f4a2713aSLionel Sambuc  // CHECK-NEXT: call i8* @objc_storeWeak(i8** [[SLOT]], i8* null)
226*f4a2713aSLionel Sambuc  // CHECK-NEXT: ret void
227*f4a2713aSLionel Sambuc
228*f4a2713aSLionel Sambuc  // CHECK-LABEL:    define internal void @__copy_helper_block_
229*f4a2713aSLionel Sambuc  // 0x8 - FIELD_IS_BYREF (no FIELD_IS_WEAK because clang in control)
230*f4a2713aSLionel Sambuc  // CHECK:      call void @_Block_object_assign(i8* {{%.*}}, i8* {{%.*}}, i32 8)
231*f4a2713aSLionel Sambuc
232*f4a2713aSLionel Sambuc  // CHECK-LABEL:    define internal void @__destroy_helper_block_
233*f4a2713aSLionel Sambuc  // 0x8 - FIELD_IS_BYREF (no FIELD_IS_WEAK because clang in control)
234*f4a2713aSLionel Sambuc  // CHECK:      call void @_Block_object_dispose(i8* {{%.*}}, i32 8)
235*f4a2713aSLionel Sambuc}
236*f4a2713aSLionel Sambuc
237*f4a2713aSLionel Sambucvoid test7(void) {
238*f4a2713aSLionel Sambuc  id test7_source(void);
239*f4a2713aSLionel Sambuc  void test7_helper(void (^)(void));
240*f4a2713aSLionel Sambuc  void test7_consume(id);
241*f4a2713aSLionel Sambuc  __weak id var = test7_source();
242*f4a2713aSLionel Sambuc  test7_helper(^{ test7_consume(var); });
243*f4a2713aSLionel Sambuc
244*f4a2713aSLionel Sambuc  // CHECK-LABEL:    define void @test7()
245*f4a2713aSLionel Sambuc  // CHECK:      [[VAR:%.*]] = alloca i8*,
246*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
247*f4a2713aSLionel Sambuc  // CHECK:      [[T0:%.*]] = call i8* @test7_source()
248*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
249*f4a2713aSLionel Sambuc  // CHECK-NEXT: call i8* @objc_initWeak(i8** [[VAR]], i8* [[T1]])
250*f4a2713aSLionel Sambuc  // CHECK-NEXT: call void @objc_release(i8* [[T1]])
251*f4a2713aSLionel Sambuc  // 0x42800000 - has signature, copy/dispose helpers, as well as BLOCK_HAS_EXTENDED_LAYOUT
252*f4a2713aSLionel Sambuc  // CHECK:      store i32 -1040187392,
253*f4a2713aSLionel Sambuc  // CHECK:      [[SLOT:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
254*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_loadWeakRetained(i8** [[VAR]])
255*f4a2713aSLionel Sambuc  // CHECK-NEXT: call i8* @objc_initWeak(i8** [[SLOT]], i8* [[T0]])
256*f4a2713aSLionel Sambuc  // CHECK:      call void @test7_helper(
257*f4a2713aSLionel Sambuc  // CHECK-NEXT: call void @objc_destroyWeak(i8** {{%.*}})
258*f4a2713aSLionel Sambuc  // CHECK-NEXT: call void @objc_destroyWeak(i8** [[VAR]])
259*f4a2713aSLionel Sambuc  // CHECK: ret void
260*f4a2713aSLionel Sambuc
261*f4a2713aSLionel Sambuc  // CHECK-LABEL:    define internal void @__test7_block_invoke
262*f4a2713aSLionel Sambuc  // CHECK:      [[SLOT:%.*]] = getelementptr inbounds [[BLOCK_T]]* {{%.*}}, i32 0, i32 5
263*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_loadWeakRetained(i8** [[SLOT]])
264*f4a2713aSLionel Sambuc  // CHECK-NEXT: call void @test7_consume(i8* [[T0]])
265*f4a2713aSLionel Sambuc  // CHECK-NEXT: call void @objc_release(i8* [[T0]])
266*f4a2713aSLionel Sambuc  // CHECK: ret void
267*f4a2713aSLionel Sambuc
268*f4a2713aSLionel Sambuc  // CHECK-LABEL:    define internal void @__copy_helper_block_
269*f4a2713aSLionel Sambuc  // CHECK:      getelementptr
270*f4a2713aSLionel Sambuc  // CHECK-NEXT: getelementptr
271*f4a2713aSLionel Sambuc  // CHECK-NEXT: call void @objc_copyWeak(
272*f4a2713aSLionel Sambuc
273*f4a2713aSLionel Sambuc  // CHECK-LABEL:    define internal void @__destroy_helper_block_
274*f4a2713aSLionel Sambuc  // CHECK:      getelementptr
275*f4a2713aSLionel Sambuc  // CHECK-NEXT: call void @objc_destroyWeak(
276*f4a2713aSLionel Sambuc}
277*f4a2713aSLionel Sambuc
278*f4a2713aSLionel Sambuc@interface Test8 @end
279*f4a2713aSLionel Sambuc@implementation Test8
280*f4a2713aSLionel Sambuc- (void) test {
281*f4a2713aSLionel Sambuc// CHECK:    define internal void @"\01-[Test8 test]"
282*f4a2713aSLionel Sambuc// CHECK:      [[SELF:%.*]] = alloca [[TEST8:%.*]]*,
283*f4a2713aSLionel Sambuc// CHECK-NEXT: alloca i8*
284*f4a2713aSLionel Sambuc// CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
285*f4a2713aSLionel Sambuc// CHECK: store
286*f4a2713aSLionel Sambuc// CHECK-NEXT: store
287*f4a2713aSLionel Sambuc// CHECK:      [[D0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
288*f4a2713aSLionel Sambuc// CHECK:      [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
289*f4a2713aSLionel Sambuc// CHECK-NEXT: [[T1:%.*]] = load [[TEST8]]** [[SELF]],
290*f4a2713aSLionel Sambuc// CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST8]]* [[T1]] to i8*
291*f4a2713aSLionel Sambuc// CHECK-NEXT: [[T3:%.*]] = call i8* @objc_retain(i8* [[T2]])
292*f4a2713aSLionel Sambuc// CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to [[TEST8]]*
293*f4a2713aSLionel Sambuc// CHECK-NEXT: store [[TEST8]]* [[T4]], [[TEST8]]** [[T0]]
294*f4a2713aSLionel Sambuc// CHECK-NEXT: bitcast [[BLOCK_T]]* [[BLOCK]] to
295*f4a2713aSLionel Sambuc// CHECK: call void @test8_helper(
296*f4a2713aSLionel Sambuc// CHECK-NEXT: [[T1:%.*]] = load [[TEST8]]** [[D0]]
297*f4a2713aSLionel Sambuc// CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST8]]* [[T1]] to i8*
298*f4a2713aSLionel Sambuc// CHECK-NEXT: call void @objc_release(i8* [[T2]])
299*f4a2713aSLionel Sambuc// CHECK: ret void
300*f4a2713aSLionel Sambuc
301*f4a2713aSLionel Sambuc  extern void test8_helper(void (^)(void));
302*f4a2713aSLionel Sambuc  test8_helper(^{ (void) self; });
303*f4a2713aSLionel Sambuc}
304*f4a2713aSLionel Sambuc@end
305*f4a2713aSLionel Sambuc
306*f4a2713aSLionel Sambucid test9(void) {
307*f4a2713aSLionel Sambuc  typedef id __attribute__((ns_returns_retained)) blocktype(void);
308*f4a2713aSLionel Sambuc  extern void test9_consume_block(blocktype^);
309*f4a2713aSLionel Sambuc  return ^blocktype {
310*f4a2713aSLionel Sambuc      extern id test9_produce(void);
311*f4a2713aSLionel Sambuc      return test9_produce();
312*f4a2713aSLionel Sambuc  }();
313*f4a2713aSLionel Sambuc
314*f4a2713aSLionel Sambuc// CHECK-LABEL:    define i8* @test9(
315*f4a2713aSLionel Sambuc// CHECK:      load i8** getelementptr
316*f4a2713aSLionel Sambuc// CHECK-NEXT: bitcast i8*
317*f4a2713aSLionel Sambuc// CHECK-NEXT: call i8*
318*f4a2713aSLionel Sambuc// CHECK-NEXT: tail call i8* @objc_autoreleaseReturnValue
319*f4a2713aSLionel Sambuc// CHECK-NEXT: ret i8*
320*f4a2713aSLionel Sambuc
321*f4a2713aSLionel Sambuc// CHECK:      call i8* @test9_produce()
322*f4a2713aSLionel Sambuc// CHECK-NEXT: call i8* @objc_retain
323*f4a2713aSLionel Sambuc// CHECK-NEXT: ret i8*
324*f4a2713aSLionel Sambuc}
325*f4a2713aSLionel Sambuc
326*f4a2713aSLionel Sambuc// rdar://problem/9814099
327*f4a2713aSLionel Sambuc// Test that we correctly initialize __block variables
328*f4a2713aSLionel Sambuc// when the initialization captures the variable.
329*f4a2713aSLionel Sambucvoid test10a(void) {
330*f4a2713aSLionel Sambuc  __block void (^block)(void) = ^{ block(); };
331*f4a2713aSLionel Sambuc  // CHECK-LABEL:    define void @test10a()
332*f4a2713aSLionel Sambuc  // CHECK:      [[BYREF:%.*]] = alloca [[BYREF_T:%.*]],
333*f4a2713aSLionel Sambuc
334*f4a2713aSLionel Sambuc  // Zero-initialization before running the initializer.
335*f4a2713aSLionel Sambuc  // CHECK:      [[T0:%.*]] = getelementptr inbounds [[BYREF_T]]* [[BYREF]], i32 0, i32 6
336*f4a2713aSLionel Sambuc  // CHECK-NEXT: store void ()* null, void ()** [[T0]], align 8
337*f4a2713aSLionel Sambuc
338*f4a2713aSLionel Sambuc  // Run the initializer as an assignment.
339*f4a2713aSLionel Sambuc  // CHECK:      [[T0:%.*]] = bitcast void ()* {{%.*}} to i8*
340*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainBlock(i8* [[T0]])
341*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to void ()*
342*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds [[BYREF_T]]* [[BYREF]], i32 0, i32 1
343*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T4:%.*]] = load [[BYREF_T]]** [[T3]]
344*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T5:%.*]] = getelementptr inbounds [[BYREF_T]]* [[T4]], i32 0, i32 6
345*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T6:%.*]] = load void ()** [[T5]], align 8
346*f4a2713aSLionel Sambuc  // CHECK-NEXT: store void ()* {{%.*}}, void ()** [[T5]], align 8
347*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T7:%.*]] = bitcast void ()* [[T6]] to i8*
348*f4a2713aSLionel Sambuc  // CHECK-NEXT: call void @objc_release(i8* [[T7]])
349*f4a2713aSLionel Sambuc
350*f4a2713aSLionel Sambuc  // Destroy at end of function.
351*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[SLOT:%.*]] = getelementptr inbounds [[BYREF_T]]* [[BYREF]], i32 0, i32 6
352*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T0:%.*]] = bitcast [[BYREF_T]]* [[BYREF]] to i8*
353*f4a2713aSLionel Sambuc  // CHECK-NEXT: call void @_Block_object_dispose(i8* [[T0]], i32 8)
354*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T1:%.*]] = load void ()** [[SLOT]]
355*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T2:%.*]] = bitcast void ()* [[T1]] to i8*
356*f4a2713aSLionel Sambuc  // CHECK-NEXT: call void @objc_release(i8* [[T2]])
357*f4a2713aSLionel Sambuc  // CHECK: ret void
358*f4a2713aSLionel Sambuc}
359*f4a2713aSLionel Sambuc
360*f4a2713aSLionel Sambuc// <rdar://problem/10402698>: do this copy and dispose with
361*f4a2713aSLionel Sambuc// objc_retainBlock/release instead of _Block_object_assign/destroy.
362*f4a2713aSLionel Sambuc// We can also use _Block_object_assign/destroy with
363*f4a2713aSLionel Sambuc// BLOCK_FIELD_IS_BLOCK as long as we don't pass BLOCK_BYREF_CALLER.
364*f4a2713aSLionel Sambuc
365*f4a2713aSLionel Sambuc// CHECK-LABEL: define internal void @__Block_byref_object_copy
366*f4a2713aSLionel Sambuc// CHECK:      [[D0:%.*]] = load i8** {{%.*}}
367*f4a2713aSLionel Sambuc// CHECK-NEXT: [[D1:%.*]] = bitcast i8* [[D0]] to [[BYREF_T]]*
368*f4a2713aSLionel Sambuc// CHECK-NEXT: [[D2:%.*]] = getelementptr inbounds [[BYREF_T]]* [[D1]], i32 0, i32 6
369*f4a2713aSLionel Sambuc// CHECK-NEXT: [[S0:%.*]] = load i8** {{%.*}}
370*f4a2713aSLionel Sambuc// CHECK-NEXT: [[S1:%.*]] = bitcast i8* [[S0]] to [[BYREF_T]]*
371*f4a2713aSLionel Sambuc// CHECK-NEXT: [[S2:%.*]] = getelementptr inbounds [[BYREF_T]]* [[S1]], i32 0, i32 6
372*f4a2713aSLionel Sambuc// CHECK-NEXT: [[T0:%.*]] = load void ()** [[S2]], align 8
373*f4a2713aSLionel Sambuc// CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8*
374*f4a2713aSLionel Sambuc// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]])
375*f4a2713aSLionel Sambuc// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to void ()*
376*f4a2713aSLionel Sambuc// CHECK-NEXT: store void ()* [[T3]], void ()** [[D2]], align 8
377*f4a2713aSLionel Sambuc// CHECK: ret void
378*f4a2713aSLionel Sambuc
379*f4a2713aSLionel Sambuc// CHECK-LABEL: define internal void @__Block_byref_object_dispose
380*f4a2713aSLionel Sambuc// CHECK:      [[T0:%.*]] = load i8** {{%.*}}
381*f4a2713aSLionel Sambuc// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[BYREF_T]]*
382*f4a2713aSLionel Sambuc// CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [[BYREF_T]]* [[T1]], i32 0, i32 6
383*f4a2713aSLionel Sambuc// CHECK-NEXT: [[T3:%.*]] = load void ()** [[T2]]
384*f4a2713aSLionel Sambuc// CHECK-NEXT: [[T4:%.*]] = bitcast void ()* [[T3]] to i8*
385*f4a2713aSLionel Sambuc// CHECK-NEXT: call void @objc_release(i8* [[T4]])
386*f4a2713aSLionel Sambuc// CHECK-NEXT: ret void
387*f4a2713aSLionel Sambuc
388*f4a2713aSLionel Sambuc// Test that we correctly assign to __block variables when the
389*f4a2713aSLionel Sambuc// assignment captures the variable.
390*f4a2713aSLionel Sambucvoid test10b(void) {
391*f4a2713aSLionel Sambuc  __block void (^block)(void);
392*f4a2713aSLionel Sambuc  block = ^{ block(); };
393*f4a2713aSLionel Sambuc
394*f4a2713aSLionel Sambuc  // CHECK-LABEL:    define void @test10b()
395*f4a2713aSLionel Sambuc  // CHECK:      [[BYREF:%.*]] = alloca [[BYREF_T:%.*]],
396*f4a2713aSLionel Sambuc
397*f4a2713aSLionel Sambuc  // Zero-initialize.
398*f4a2713aSLionel Sambuc  // CHECK:      [[T0:%.*]] = getelementptr inbounds [[BYREF_T]]* [[BYREF]], i32 0, i32 6
399*f4a2713aSLionel Sambuc  // CHECK-NEXT: store void ()* null, void ()** [[T0]], align 8
400*f4a2713aSLionel Sambuc
401*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[SLOT:%.*]] = getelementptr inbounds [[BYREF_T]]* [[BYREF]], i32 0, i32 6
402*f4a2713aSLionel Sambuc
403*f4a2713aSLionel Sambuc  // The assignment.
404*f4a2713aSLionel Sambuc  // CHECK:      [[T0:%.*]] = bitcast void ()* {{%.*}} to i8*
405*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainBlock(i8* [[T0]])
406*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to void ()*
407*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds [[BYREF_T]]* [[BYREF]], i32 0, i32 1
408*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T4:%.*]] = load [[BYREF_T]]** [[T3]]
409*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T5:%.*]] = getelementptr inbounds [[BYREF_T]]* [[T4]], i32 0, i32 6
410*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T6:%.*]] = load void ()** [[T5]], align 8
411*f4a2713aSLionel Sambuc  // CHECK-NEXT: store void ()* {{%.*}}, void ()** [[T5]], align 8
412*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T7:%.*]] = bitcast void ()* [[T6]] to i8*
413*f4a2713aSLionel Sambuc  // CHECK-NEXT: call void @objc_release(i8* [[T7]])
414*f4a2713aSLionel Sambuc
415*f4a2713aSLionel Sambuc  // Destroy at end of function.
416*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T0:%.*]] = bitcast [[BYREF_T]]* [[BYREF]] to i8*
417*f4a2713aSLionel Sambuc  // CHECK-NEXT: call void @_Block_object_dispose(i8* [[T0]], i32 8)
418*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T1:%.*]] = load void ()** [[SLOT]]
419*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T2:%.*]] = bitcast void ()* [[T1]] to i8*
420*f4a2713aSLionel Sambuc  // CHECK-NEXT: call void @objc_release(i8* [[T2]])
421*f4a2713aSLionel Sambuc  // CHECK: ret void
422*f4a2713aSLionel Sambuc}
423*f4a2713aSLionel Sambuc
424*f4a2713aSLionel Sambuc// rdar://problem/10088932
425*f4a2713aSLionel Sambucvoid test11_helper(id);
426*f4a2713aSLionel Sambucvoid test11a(void) {
427*f4a2713aSLionel Sambuc  int x;
428*f4a2713aSLionel Sambuc  test11_helper(^{ (void) x; });
429*f4a2713aSLionel Sambuc
430*f4a2713aSLionel Sambuc  // CHECK-LABEL:    define void @test11a()
431*f4a2713aSLionel Sambuc  // CHECK:      [[X:%.*]] = alloca i32, align 4
432*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]], align 8
433*f4a2713aSLionel Sambuc  // CHECK:      [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to void ()*
434*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8*
435*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]])
436*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to void ()*
437*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T4:%.*]] = bitcast void ()* [[T3]] to i8*
438*f4a2713aSLionel Sambuc  // CHECK-NEXT: call void @test11_helper(i8* [[T4]])
439*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T5:%.*]] = bitcast void ()* [[T3]] to i8*
440*f4a2713aSLionel Sambuc  // CHECK-NEXT: call void @objc_release(i8* [[T5]])
441*f4a2713aSLionel Sambuc  // CHECK: ret void
442*f4a2713aSLionel Sambuc}
443*f4a2713aSLionel Sambucvoid test11b(void) {
444*f4a2713aSLionel Sambuc  int x;
445*f4a2713aSLionel Sambuc  id b = ^{ (void) x; };
446*f4a2713aSLionel Sambuc
447*f4a2713aSLionel Sambuc  // CHECK-LABEL:    define void @test11b()
448*f4a2713aSLionel Sambuc  // CHECK:      [[X:%.*]] = alloca i32, align 4
449*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[B:%.*]] = alloca i8*, align 8
450*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]], align 8
451*f4a2713aSLionel Sambuc  // CHECK:      [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to void ()*
452*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8*
453*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]])
454*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to void ()*
455*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T4:%.*]] = bitcast void ()* [[T3]] to i8*
456*f4a2713aSLionel Sambuc  // CHECK-NEXT: store i8* [[T4]], i8** [[B]], align 8
457*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T5:%.*]] = load i8** [[B]]
458*f4a2713aSLionel Sambuc  // CHECK-NEXT: call void @objc_release(i8* [[T5]])
459*f4a2713aSLionel Sambuc  // CHECK: ret void
460*f4a2713aSLionel Sambuc}
461*f4a2713aSLionel Sambuc
462*f4a2713aSLionel Sambuc// rdar://problem/9979150
463*f4a2713aSLionel Sambuc@interface Test12
464*f4a2713aSLionel Sambuc@property (strong) void(^ablock)(void);
465*f4a2713aSLionel Sambuc@property (nonatomic, strong) void(^nblock)(void);
466*f4a2713aSLionel Sambuc@end
467*f4a2713aSLionel Sambuc@implementation Test12
468*f4a2713aSLionel Sambuc@synthesize ablock, nblock;
469*f4a2713aSLionel Sambuc// CHECK:    define internal void ()* @"\01-[Test12 ablock]"(
470*f4a2713aSLionel Sambuc// CHECK:    call i8* @objc_getProperty(i8* {{%.*}}, i8* {{%.*}}, i64 {{%.*}}, i1 zeroext true)
471*f4a2713aSLionel Sambuc
472*f4a2713aSLionel Sambuc// CHECK:    define internal void @"\01-[Test12 setAblock:]"(
473*f4a2713aSLionel Sambuc// CHECK:    call void @objc_setProperty(i8* {{%.*}}, i8* {{%.*}}, i64 {{%.*}}, i8* {{%.*}}, i1 zeroext true, i1 zeroext true)
474*f4a2713aSLionel Sambuc
475*f4a2713aSLionel Sambuc// CHECK:    define internal void ()* @"\01-[Test12 nblock]"(
476*f4a2713aSLionel Sambuc// CHECK:    call i8* @objc_getProperty(i8* {{%.*}}, i8* {{%.*}}, i64 {{%.*}}, i1 zeroext false)
477*f4a2713aSLionel Sambuc
478*f4a2713aSLionel Sambuc// CHECK:    define internal void @"\01-[Test12 setNblock:]"(
479*f4a2713aSLionel Sambuc// CHECK:    call void @objc_setProperty(i8* {{%.*}}, i8* {{%.*}}, i64 {{%.*}}, i8* {{%.*}}, i1 zeroext false, i1 zeroext true)
480*f4a2713aSLionel Sambuc@end
481*f4a2713aSLionel Sambuc
482*f4a2713aSLionel Sambuc// rdar://problem/10131784
483*f4a2713aSLionel Sambucvoid test13(id x) {
484*f4a2713aSLionel Sambuc  extern void test13_helper(id);
485*f4a2713aSLionel Sambuc  extern void test13_use(void(^)(void));
486*f4a2713aSLionel Sambuc
487*f4a2713aSLionel Sambuc  void (^b)(void) = (x ? ^{test13_helper(x);} : 0);
488*f4a2713aSLionel Sambuc  test13_use(b);
489*f4a2713aSLionel Sambuc
490*f4a2713aSLionel Sambuc  // CHECK-LABEL:    define void @test13(
491*f4a2713aSLionel Sambuc  // CHECK:      [[X:%.*]] = alloca i8*, align 8
492*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[B:%.*]] = alloca void ()*, align 8
493*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:.*]], align 8
494*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[CLEANUP_ACTIVE:%.*]] = alloca i1
495*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_retain(i8* {{%.*}})
496*f4a2713aSLionel Sambuc  // CHECK-NEXT: store i8* [[T0]], i8** [[X]], align 8
497*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[CLEANUP_ADDR:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
498*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T0:%.*]] = load i8** [[X]], align 8
499*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T1:%.*]] = icmp ne i8* [[T0]], null
500*f4a2713aSLionel Sambuc  // CHECK-NEXT: store i1 false, i1* [[CLEANUP_ACTIVE]]
501*f4a2713aSLionel Sambuc  // CHECK-NEXT: br i1 [[T1]],
502*f4a2713aSLionel Sambuc
503*f4a2713aSLionel Sambuc  // CHECK-NOT:  br
504*f4a2713aSLionel Sambuc  // CHECK:      [[CAPTURE:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
505*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T0:%.*]] = load i8** [[X]], align 8
506*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]])
507*f4a2713aSLionel Sambuc  // CHECK-NEXT: store i8* [[T1]], i8** [[CAPTURE]], align 8
508*f4a2713aSLionel Sambuc  // CHECK-NEXT: store i1 true, i1* [[CLEANUP_ACTIVE]]
509*f4a2713aSLionel Sambuc  // CHECK-NEXT: bitcast [[BLOCK_T]]* [[BLOCK]] to void ()*
510*f4a2713aSLionel Sambuc  // CHECK-NEXT: br label
511*f4a2713aSLionel Sambuc  // CHECK:      br label
512*f4a2713aSLionel Sambuc  // CHECK:      [[T0:%.*]] = phi void ()*
513*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8*
514*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]])
515*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to void ()*
516*f4a2713aSLionel Sambuc  // CHECK-NEXT: store void ()* [[T3]], void ()** [[B]], align 8
517*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T0:%.*]] = load void ()** [[B]], align 8
518*f4a2713aSLionel Sambuc  // CHECK-NEXT: call void @test13_use(void ()* [[T0]])
519*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T0:%.*]] = load void ()** [[B]]
520*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8*
521*f4a2713aSLionel Sambuc  // CHECK-NEXT: call void @objc_release(i8* [[T1]])
522*f4a2713aSLionel Sambuc
523*f4a2713aSLionel Sambuc  // CHECK-NEXT: [[T0:%.*]] = load i1* [[CLEANUP_ACTIVE]]
524*f4a2713aSLionel Sambuc  // CHECK-NEXT: br i1 [[T0]]
525*f4a2713aSLionel Sambuc  // CHECK:      [[T0:%.*]] = load i8** [[CLEANUP_ADDR]]
526*f4a2713aSLionel Sambuc  // CHECK-NEXT: call void @objc_release(i8* [[T0]])
527*f4a2713aSLionel Sambuc  // CHECK-NEXT: br label
528*f4a2713aSLionel Sambuc
529*f4a2713aSLionel Sambuc  // CHECK:      [[T0:%.*]] = load i8** [[X]]
530*f4a2713aSLionel Sambuc  // CHECK-NEXT: call void @objc_release(i8* [[T0]])
531*f4a2713aSLionel Sambuc  // CHECK-NEXT: ret void
532*f4a2713aSLionel Sambuc}
533*f4a2713aSLionel Sambuc
534*f4a2713aSLionel Sambuc// <rdar://problem/10907510>
535*f4a2713aSLionel Sambucvoid test14() {
536*f4a2713aSLionel Sambuc  void (^const x[1])(void) = { ^{} };
537*f4a2713aSLionel Sambuc}
538*f4a2713aSLionel Sambuc
539*f4a2713aSLionel Sambuc// rdar://11149025
540*f4a2713aSLionel Sambuc// Don't make invalid ASTs and crash.
541*f4a2713aSLionel Sambucvoid test15_helper(void (^block)(void), int x);
542*f4a2713aSLionel Sambucvoid test15(int a) {
543*f4a2713aSLionel Sambuc  test15_helper(^{ (void) a; }, ({ a; }));
544*f4a2713aSLionel Sambuc}
545*f4a2713aSLionel Sambuc
546*f4a2713aSLionel Sambuc// rdar://11016025
547*f4a2713aSLionel Sambucvoid test16() {
548*f4a2713aSLionel Sambuc  void (^BLKVAR)(void) = ^{ BLKVAR(); };
549*f4a2713aSLionel Sambuc
550*f4a2713aSLionel Sambuc  // CHECK-LABEL: define void @test16(
551*f4a2713aSLionel Sambuc  // CHECK: [[BLKVAR:%.*]]  = alloca void ()*, align 8
552*f4a2713aSLionel Sambuc  // CHECK-NEXT:  [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
553*f4a2713aSLionel Sambuc  // CHECK-NEXT:  [[SLOTREL:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
554*f4a2713aSLionel Sambuc  // CHECK-NEXT:  store void ()* null, void ()** [[BLKVAR]], align 8
555*f4a2713aSLionel Sambuc}
556*f4a2713aSLionel Sambuc
557*f4a2713aSLionel Sambuc// rdar://12151005
558*f4a2713aSLionel Sambuc//
559*f4a2713aSLionel Sambuc// This is an intentional exception to our conservative jump-scope
560*f4a2713aSLionel Sambuc// checking for full-expressions containing block literals with
561*f4a2713aSLionel Sambuc// non-trivial cleanups: if the block literal appears in the operand
562*f4a2713aSLionel Sambuc// of a return statement, there's no need to extend its lifetime.
563*f4a2713aSLionel Sambucid (^test17(id self, int which))(void) {
564*f4a2713aSLionel Sambuc  switch (which) {
565*f4a2713aSLionel Sambuc  case 1: return ^{ return self; };
566*f4a2713aSLionel Sambuc  case 0: return ^{ return self; };
567*f4a2713aSLionel Sambuc  }
568*f4a2713aSLionel Sambuc  return (void*) 0;
569*f4a2713aSLionel Sambuc}
570*f4a2713aSLionel Sambuc// CHECK-LABEL:    define i8* ()* @test17(
571*f4a2713aSLionel Sambuc// CHECK:      [[RET:%.*]] = alloca i8* ()*, align
572*f4a2713aSLionel Sambuc// CHECK-NEXT: [[SELF:%.*]] = alloca i8*,
573*f4a2713aSLionel Sambuc// CHECK:      [[B0:%.*]] = alloca [[BLOCK:<.*>]], align
574*f4a2713aSLionel Sambuc// CHECK:      [[B1:%.*]] = alloca [[BLOCK]], align
575*f4a2713aSLionel Sambuc// CHECK:      [[T0:%.*]] = call i8* @objc_retain(i8*
576*f4a2713aSLionel Sambuc// CHECK-NEXT: store i8* [[T0]], i8** [[SELF]], align
577*f4a2713aSLionel Sambuc// CHECK-NOT:  objc_retain
578*f4a2713aSLionel Sambuc// CHECK-NOT:  objc_release
579*f4a2713aSLionel Sambuc// CHECK:      [[DESTROY:%.*]] = getelementptr inbounds [[BLOCK]]* [[B0]], i32 0, i32 5
580*f4a2713aSLionel Sambuc// CHECK-NOT:  objc_retain
581*f4a2713aSLionel Sambuc// CHECK-NOT:  objc_release
582*f4a2713aSLionel Sambuc// CHECK:      [[T0:%.*]] = getelementptr inbounds [[BLOCK]]* [[B0]], i32 0, i32 5
583*f4a2713aSLionel Sambuc// CHECK-NEXT: [[T1:%.*]] = load i8** [[SELF]], align
584*f4a2713aSLionel Sambuc// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]])
585*f4a2713aSLionel Sambuc// CHECK-NEXT: store i8* [[T2]], i8** [[T0]],
586*f4a2713aSLionel Sambuc// CHECK-NEXT: [[T0:%.*]] = bitcast [[BLOCK]]* [[B0]] to i8* ()*
587*f4a2713aSLionel Sambuc// CHECK-NEXT: [[T1:%.*]] = bitcast i8* ()* [[T0]] to i8*
588*f4a2713aSLionel Sambuc// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]])
589*f4a2713aSLionel Sambuc// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to i8* ()*
590*f4a2713aSLionel Sambuc// CHECK-NEXT: store i8* ()* [[T3]], i8* ()** [[RET]]
591*f4a2713aSLionel Sambuc// CHECK-NEXT: [[T0:%.*]] = load i8** [[DESTROY]]
592*f4a2713aSLionel Sambuc// CHECK-NEXT: call void @objc_release(i8* [[T0]])
593*f4a2713aSLionel Sambuc// CHECK-NEXT: store i32
594*f4a2713aSLionel Sambuc// CHECK-NEXT: br label
595*f4a2713aSLionel Sambuc// CHECK-NOT:  objc_retain
596*f4a2713aSLionel Sambuc// CHECK-NOT:  objc_release
597*f4a2713aSLionel Sambuc// CHECK:      [[DESTROY:%.*]] = getelementptr inbounds [[BLOCK]]* [[B1]], i32 0, i32 5
598*f4a2713aSLionel Sambuc// CHECK-NOT:  objc_retain
599*f4a2713aSLionel Sambuc// CHECK-NOT:  objc_release
600*f4a2713aSLionel Sambuc// CHECK:      [[T0:%.*]] = getelementptr inbounds [[BLOCK]]* [[B1]], i32 0, i32 5
601*f4a2713aSLionel Sambuc// CHECK-NEXT: [[T1:%.*]] = load i8** [[SELF]], align
602*f4a2713aSLionel Sambuc// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]])
603*f4a2713aSLionel Sambuc// CHECK-NEXT: store i8* [[T2]], i8** [[T0]],
604*f4a2713aSLionel Sambuc// CHECK-NEXT: [[T0:%.*]] = bitcast [[BLOCK]]* [[B1]] to i8* ()*
605*f4a2713aSLionel Sambuc// CHECK-NEXT: [[T1:%.*]] = bitcast i8* ()* [[T0]] to i8*
606*f4a2713aSLionel Sambuc// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]])
607*f4a2713aSLionel Sambuc// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to i8* ()*
608*f4a2713aSLionel Sambuc// CHECK-NEXT: store i8* ()* [[T3]], i8* ()** [[RET]]
609*f4a2713aSLionel Sambuc// CHECK-NEXT: [[T0:%.*]] = load i8** [[DESTROY]]
610*f4a2713aSLionel Sambuc// CHECK-NEXT: call void @objc_release(i8* [[T0]])
611*f4a2713aSLionel Sambuc// CHECK-NEXT: store i32
612*f4a2713aSLionel Sambuc// CHECK-NEXT: br label
613*f4a2713aSLionel Sambuc
614*f4a2713aSLionel Sambucvoid test18(id x) {
615*f4a2713aSLionel Sambuc// CHECK-UNOPT-LABEL:    define void @test18(
616*f4a2713aSLionel Sambuc// CHECK-UNOPT:      [[X:%.*]] = alloca i8*,
617*f4a2713aSLionel Sambuc// CHECK-UNOPT-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
618*f4a2713aSLionel Sambuc// CHECK-UNOPT-NEXT: store i8* null, i8** [[X]]
619*f4a2713aSLionel Sambuc// CHECK-UNOPT-NEXT: call void @objc_storeStrong(i8** [[X]],
620*f4a2713aSLionel Sambuc// CHECK-UNOPT-NEXT: [[SLOTREL:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
621*f4a2713aSLionel Sambuc// CHECK-UNOPT:      [[SLOT:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
622*f4a2713aSLionel Sambuc// CHECK-UNOPT-NEXT: [[T0:%.*]] = load i8** [[X]],
623*f4a2713aSLionel Sambuc// CHECK-UNOPT-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]])
624*f4a2713aSLionel Sambuc// CHECK-UNOPT-NEXT: store i8* [[T1]], i8** [[SLOT]],
625*f4a2713aSLionel Sambuc// CHECK-UNOPT-NEXT: bitcast
626*f4a2713aSLionel Sambuc// CHECK-UNOPT-NEXT: call void @test18_helper(
627*f4a2713aSLionel Sambuc// CHECK-UNOPT-NEXT: call void @objc_storeStrong(i8** [[SLOTREL]], i8* null) [[NUW:#[0-9]+]]
628*f4a2713aSLionel Sambuc// CHECK-UNOPT-NEXT: call void @objc_storeStrong(i8** [[X]], i8* null) [[NUW]]
629*f4a2713aSLionel Sambuc// CHECK-UNOPT-NEXT: ret void
630*f4a2713aSLionel Sambuc  extern void test18_helper(id (^)(void));
631*f4a2713aSLionel Sambuc  test18_helper(^{ return x; });
632*f4a2713aSLionel Sambuc
633*f4a2713aSLionel Sambuc// CHECK-UNOPT-LABEL:    define internal void @__copy_helper_block_
634*f4a2713aSLionel Sambuc// CHECK-UNOPT:      [[T0:%.*]] = load i8**
635*f4a2713aSLionel Sambuc// CHECK-UNOPT-NEXT: [[SRC:%.*]] = bitcast i8* [[T0]] to [[BLOCK_T]]*
636*f4a2713aSLionel Sambuc// CHECK-UNOPT-NEXT: [[T0:%.*]] = load i8**
637*f4a2713aSLionel Sambuc// CHECK-UNOPT-NEXT: [[DST:%.*]] = bitcast i8* [[T0]] to [[BLOCK_T]]*
638*f4a2713aSLionel Sambuc// CHECK-UNOPT-NEXT: [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[SRC]], i32 0, i32 5
639*f4a2713aSLionel Sambuc// CHECK-UNOPT-NEXT: [[T1:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[DST]], i32 0, i32 5
640*f4a2713aSLionel Sambuc// CHECK-UNOPT-NEXT: [[T2:%.*]] = load i8** [[T0]]
641*f4a2713aSLionel Sambuc// CHECK-UNOPT-NEXT: store i8* null, i8** [[T1]]
642*f4a2713aSLionel Sambuc// CHECK-UNOPT-NEXT: call void @objc_storeStrong(i8** [[T1]], i8* [[T2]]) [[NUW]]
643*f4a2713aSLionel Sambuc// CHECK-UNOPT-NEXT: ret void
644*f4a2713aSLionel Sambuc
645*f4a2713aSLionel Sambuc// CHECK-UNOPT-LABEL:    define internal void @__destroy_helper_block_
646*f4a2713aSLionel Sambuc// CHECK-UNOPT:      [[T0:%.*]] = load i8**
647*f4a2713aSLionel Sambuc// CHECK-UNOPT-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[BLOCK_T]]*
648*f4a2713aSLionel Sambuc// CHECK-UNOPT-NEXT: [[T2:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[T1]], i32 0, i32 5
649*f4a2713aSLionel Sambuc// CHECK-UNOPT-NEXT: call void @objc_storeStrong(i8** [[T2]], i8* null)
650*f4a2713aSLionel Sambuc// CHECK-UNOPT-NEXT: ret void
651*f4a2713aSLionel Sambuc}
652*f4a2713aSLionel Sambuc
653*f4a2713aSLionel Sambuc// rdar://13588325
654*f4a2713aSLionel Sambucvoid test19_sink(void (^)(int));
655*f4a2713aSLionel Sambucvoid test19(void (^b)(void)) {
656*f4a2713aSLionel Sambuc// CHECK-LABEL:    define void @test19(
657*f4a2713aSLionel Sambuc//   Prologue.
658*f4a2713aSLionel Sambuc// CHECK:      [[B:%.*]] = alloca void ()*,
659*f4a2713aSLionel Sambuc// CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
660*f4a2713aSLionel Sambuc// CHECK-NEXT: [[T0:%.*]] = bitcast void ()* {{%.*}} to i8*
661*f4a2713aSLionel Sambuc// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]])
662*f4a2713aSLionel Sambuc// CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to void ()*
663*f4a2713aSLionel Sambuc// CHECK-NEXT: store void ()* [[T2]], void ()** [[B]]
664*f4a2713aSLionel Sambuc
665*f4a2713aSLionel Sambuc//   Block setup.  We skip most of this.  Note the bare retain.
666*f4a2713aSLionel Sambuc// CHECK-NEXT: [[SLOTREL:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
667*f4a2713aSLionel Sambuc// CHECK:      [[SLOT:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
668*f4a2713aSLionel Sambuc// CHECK-NEXT: [[T0:%.*]] = load void ()** [[B]],
669*f4a2713aSLionel Sambuc// CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8*
670*f4a2713aSLionel Sambuc// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]])
671*f4a2713aSLionel Sambuc// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to void ()*
672*f4a2713aSLionel Sambuc// CHECK-NEXT: store void ()* [[T3]], void ()** [[SLOT]],
673*f4a2713aSLionel Sambuc//   Call.
674*f4a2713aSLionel Sambuc// CHECK-NEXT: [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to void (i32)*
675*f4a2713aSLionel Sambuc// CHECK-NEXT: call void @test19_sink(void (i32)* [[T0]])
676*f4a2713aSLionel Sambuc
677*f4a2713aSLionel Sambuc  test19_sink(^(int x) { b(); });
678*f4a2713aSLionel Sambuc
679*f4a2713aSLionel Sambuc//   Block teardown.
680*f4a2713aSLionel Sambuc// CHECK-NEXT: [[T0:%.*]] = load void ()** [[SLOTREL]]
681*f4a2713aSLionel Sambuc// CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8*
682*f4a2713aSLionel Sambuc// CHECK-NEXT: call void @objc_release(i8* [[T1]])
683*f4a2713aSLionel Sambuc
684*f4a2713aSLionel Sambuc//   Local cleanup.
685*f4a2713aSLionel Sambuc// CHECK-NEXT: [[T0:%.*]] = load void ()** [[B]]
686*f4a2713aSLionel Sambuc// CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8*
687*f4a2713aSLionel Sambuc// CHECK-NEXT: call void @objc_release(i8* [[T1]])
688*f4a2713aSLionel Sambuc
689*f4a2713aSLionel Sambuc// CHECK-NEXT: ret void
690*f4a2713aSLionel Sambuc}
691*f4a2713aSLionel Sambuc
692*f4a2713aSLionel Sambuc// CHECK: attributes [[NUW]] = { nounwind }
693*f4a2713aSLionel Sambuc// CHECK-UNOPT: attributes [[NUW]] = { nounwind }
694