1// RUN: %clang_cc1 -std=gnu++98 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-runtime-has-weak -fblocks -fobjc-arc -fexceptions -fobjc-arc-exceptions -o - %s | FileCheck -check-prefix CHECK %s
2// RUN: %clang_cc1 -std=gnu++98 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-runtime-has-weak -fblocks -fobjc-arc -fexceptions -fobjc-arc-exceptions -O1 -o - %s | FileCheck -check-prefix CHECK-O1 %s
3// RUN: %clang_cc1 -std=gnu++98 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-runtime-has-weak -fblocks -fobjc-arc -o - %s | FileCheck -check-prefix CHECK-NOEXCP %s
4
5// CHECK: [[A:.*]] = type { i64, [10 x i8*] }
6// CHECK: %[[STRUCT_BLOCK_DESCRIPTOR:.*]] = type { i64, i64 }
7// CHECK: %[[STRUCT_TEST1_S0:.*]] = type { i32 }
8// CHECK: %[[STRUCT_TRIVIAL_INTERNAL:.*]] = type { i32 }
9
10// CHECK: [[LAYOUT0:@.*]] = private unnamed_addr constant [3 x i8] c" 9\00"
11
12// rdar://13045269
13// If a __block variable requires extended layout information *and*
14// a copy/dispose helper, be sure to adjust the offsets used in copy/dispose.
15namespace test0 {
16  struct A {
17    unsigned long count;
18    id data[10];
19  };
20
21  void foo() {
22    __block A v;
23    ^{ (void)v; };
24  }
25  // CHECK-LABEL:    define{{.*}} void @_ZN5test03fooEv()
26  // CHECK:      [[V:%.*]] = alloca [[BYREF_A:%.*]], align 8
27  // CHECK:      [[T0:%.*]] = getelementptr inbounds [[BYREF_A]], [[BYREF_A]]* [[V]], i32 0, i32 4
28  // CHECK-NEXT: store i8* bitcast (void (i8*, i8*)* [[COPY_HELPER:@.*]] to i8*), i8** [[T0]]
29  // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[BYREF_A]], [[BYREF_A]]* [[V]], i32 0, i32 5
30  // CHECK-NEXT: store i8* bitcast (void (i8*)* [[DISPOSE_HELPER:@.*]] to i8*), i8** [[T0]]
31  // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[BYREF_A]], [[BYREF_A]]* [[V]], i32 0, i32 6
32  // CHECK-NEXT: store i8* getelementptr inbounds ([3 x i8], [3 x i8]* [[LAYOUT0]], i32 0, i32 0), i8** [[T0]]
33  // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[BYREF_A]], [[BYREF_A]]* [[V]], i32 0, i32 7
34  // CHECK-NEXT: call void @_ZN5test01AC1Ev([[A]]* {{[^,]*}} [[T0]])
35  // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[BYREF_A]], [[BYREF_A]]* [[V]], i32 0, i32 7
36  // CHECK: bitcast [[BYREF_A]]* [[V]] to i8*
37  // CHECK: [[T1:%.*]] = bitcast [[BYREF_A]]* [[V]] to i8*
38  // CHECK-NEXT: call void @_Block_object_dispose(i8* [[T1]], i32 8)
39  // CHECK-NEXT: call void @_ZN5test01AD1Ev([[A]]* {{[^,]*}} [[T0]])
40  // CHECK-NEXT: ret void
41
42  // CHECK:    define internal void [[COPY_HELPER]](
43  // CHECK:      [[T0:%.*]] = bitcast i8* {{.*}} to [[BYREF_A]]*
44  // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[BYREF_A]], [[BYREF_A]]* [[T0]], i32 0, i32 7
45  // CHECK-NEXT: load
46  // CHECK-NEXT: [[T2:%.*]] = bitcast i8* {{.*}} to [[BYREF_A]]*
47  // CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds [[BYREF_A]], [[BYREF_A]]* [[T2]], i32 0, i32 7
48  // CHECK-NEXT: call void @_ZN5test01AC1ERKS0_([[A]]* {{[^,]*}} [[T1]], [[A]]* nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) [[T3]])
49  // CHECK-NEXT: ret void
50
51  // CHECK:    define internal void [[DISPOSE_HELPER]](
52  // CHECK:      [[T0:%.*]] = bitcast i8* {{.*}} to [[BYREF_A]]*
53  // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[BYREF_A]], [[BYREF_A]]* [[T0]], i32 0, i32 7
54  // CHECK-NEXT: call void @_ZN5test01AD1Ev([[A]]* {{[^,]*}} [[T1]])
55  // CHECK-NEXT: ret void
56}
57
58// CHECK-LABEL: define linkonce_odr hidden void @__copy_helper_block_
59// CHECK-LABEL: define linkonce_odr hidden void @__destroy_helper_block_
60// CHECK-LABEL-O1: define linkonce_odr hidden void @__copy_helper_block_
61// CHECK-LABEL-O1: define linkonce_odr hidden void @__destroy_helper_block_
62
63namespace test1 {
64
65// Check that copy/dispose helper functions are exception safe.
66
67// CHECK-LABEL: define linkonce_odr hidden void @__copy_helper_block_ea8_32s40r48w56c15_ZTSN5test12S0E60c15_ZTSN5test12S0E(
68// CHECK: %[[BLOCK_SOURCE:.*]] = bitcast i8* %{{.*}} to <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>*
69// CHECK: %[[BLOCK_DEST:.*]] = bitcast i8* %{{.*}} to <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>*
70
71// CHECK: %[[V9:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>* %[[BLOCK_SOURCE]], i32 0, i32 5
72// CHECK: %[[V10:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>* %[[BLOCK_DEST]], i32 0, i32 5
73// CHECK: %[[BLOCKCOPY_SRC2:.*]] = load i8*, i8** %[[V9]], align 8
74// CHECK: store i8* null, i8** %[[V10]], align 8
75// CHECK: call void @llvm.objc.storeStrong(i8** %[[V10]], i8* %[[BLOCKCOPY_SRC2]])
76
77// CHECK: %[[V4:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>* %[[BLOCK_SOURCE]], i32 0, i32 6
78// CHECK: %[[V5:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>* %[[BLOCK_DEST]], i32 0, i32 6
79// CHECK: %[[BLOCKCOPY_SRC:.*]] = load i8*, i8** %[[V4]], align 8
80// CHECK: %[[V6:.*]] = bitcast i8** %[[V5]] to i8*
81// CHECK: call void @_Block_object_assign(i8* %[[V6]], i8* %[[BLOCKCOPY_SRC]], i32 8)
82
83// CHECK: %[[V7:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>* %[[BLOCK_SOURCE]], i32 0, i32 7
84// CHECK: %[[V8:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>* %[[BLOCK_DEST]], i32 0, i32 7
85// CHECK: call void @llvm.objc.copyWeak(i8** %[[V8]], i8** %[[V7]])
86
87// CHECK: %[[V11:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>* %[[BLOCK_SOURCE]], i32 0, i32 8
88// CHECK: %[[V12:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>* %[[BLOCK_DEST]], i32 0, i32 8
89// CHECK: invoke void @_ZN5test12S0C1ERKS0_(%[[STRUCT_TEST1_S0]]* {{[^,]*}} %[[V12]], %[[STRUCT_TEST1_S0]]* nonnull align 4 dereferenceable(4) %[[V11]])
90// CHECK: to label %[[INVOKE_CONT:.*]] unwind label %[[LPAD:.*]]
91
92// CHECK: [[INVOKE_CONT]]:
93// CHECK: %[[V13:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>* %[[BLOCK_SOURCE]], i32 0, i32 9
94// CHECK: %[[V14:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>* %[[BLOCK_DEST]], i32 0, i32 9
95// CHECK: invoke void @_ZN5test12S0C1ERKS0_(%[[STRUCT_TEST1_S0]]* {{[^,]*}} %[[V14]], %[[STRUCT_TEST1_S0]]* nonnull align 4 dereferenceable(4) %[[V13]])
96// CHECK: to label %[[INVOKE_CONT4:.*]] unwind label %[[LPAD3:.*]]
97
98// CHECK: [[INVOKE_CONT4]]:
99// CHECK: ret void
100
101// CHECK: [[LPAD]]:
102// CHECK: br label %[[EHCLEANUP:.*]]
103
104// CHECK: [[LPAD3]]:
105// CHECK: invoke void @_ZN5test12S0D1Ev(%[[STRUCT_TEST1_S0]]* {{[^,]*}} %[[V12]])
106// CHECK: to label %[[INVOKE_CONT5:.*]] unwind label %[[TERMINATE_LPAD:.*]]
107
108// CHECK: [[INVOKE_CONT5]]:
109// CHECK: br label %[[EHCLEANUP]]
110
111// CHECK: [[EHCLEANUP]]:
112// CHECK: call void @llvm.objc.destroyWeak(i8** %[[V8]])
113// CHECK: %[[V21:.*]] = load i8*, i8** %[[V5]], align 8
114// CHECK: call void @_Block_object_dispose(i8* %[[V21]], i32 8)
115// CHECK: call void @llvm.objc.storeStrong(i8** %[[V10]], i8* null)
116// CHECK: br label %[[EH_RESUME:.*]]
117
118// CHECK: [[EH_RESUME]]:
119// CHECK: resume { i8*, i32 }
120
121// CHECK: [[TERMINATE_LPAD]]:
122// CHECK: call void @__clang_call_terminate(
123
124// CHECK-O1-LABEL: define linkonce_odr hidden void @__copy_helper_block_ea8_32s40r48w56c15_ZTSN5test12S0E60c15_ZTSN5test12S0E(
125// CHECK-O1: call void @llvm.objc.release({{.*}}) {{.*}} !clang.imprecise_release
126// CHECK-NOEXCP: define linkonce_odr hidden void @__copy_helper_block_8_32s40r48w56c15_ZTSN5test12S0E60c15_ZTSN5test12S0E(
127
128// CHECK: define linkonce_odr hidden void @__destroy_helper_block_ea8_32s40r48w56c15_ZTSN5test12S0E60c15_ZTSN5test12S0E(
129// CHECK: %[[BLOCK:.*]] = bitcast i8* %{{.*}} to <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>*
130// CHECK: %[[V4:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>* %[[BLOCK]], i32 0, i32 5
131// CHECK: %[[V2:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>* %[[BLOCK]], i32 0, i32 6
132// CHECK: %[[V3:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>* %[[BLOCK]], i32 0, i32 7
133// CHECK: %[[V5:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>* %[[BLOCK]], i32 0, i32 8
134// CHECK: %[[V6:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]], %[[STRUCT_TRIVIAL_INTERNAL]] }>* %[[BLOCK]], i32 0, i32 9
135// CHECK: invoke void @_ZN5test12S0D1Ev(%[[STRUCT_TEST1_S0]]* {{[^,]*}} %[[V6]])
136// CHECK: to label %[[INVOKE_CONT:.*]] unwind label %[[LPAD:.*]]
137
138// CHECK: [[INVOKE_CONT]]:
139// CHECK: invoke void @_ZN5test12S0D1Ev(%[[STRUCT_TEST1_S0]]* {{[^,]*}} %[[V5]])
140// CHECK: to label %[[INVOKE_CONT2:.*]] unwind label %[[LPAD1:.*]]
141
142// CHECK: [[INVOKE_CONT2]]:
143// CHECK: call void @llvm.objc.destroyWeak(i8** %[[V3]])
144// CHECK: %[[V7:.*]] = load i8*, i8** %[[V2]], align 8
145// CHECK: call void @_Block_object_dispose(i8* %[[V7]], i32 8)
146// CHECK: call void @llvm.objc.storeStrong(i8** %[[V4]], i8* null)
147// CHECK: ret void
148
149// CHECK: [[LPAD]]:
150// CHECK: invoke void @_ZN5test12S0D1Ev(%[[STRUCT_TEST1_S0]]* {{[^,]*}} %[[V5]])
151// CHECK: to label %[[INVOKE_CONT3:.*]] unwind label %[[TERMINATE_LPAD:.*]]
152
153// CHECK: [[LPAD1]]
154// CHECK: br label %[[EHCLEANUP:.*]]
155
156// CHECK: [[INVOKE_CONT3]]:
157// CHECK: br label %[[EHCLEANUP]]
158
159// CHECK: [[EHCLEANUP]]:
160// CHECK: call void @llvm.objc.destroyWeak(i8** %[[V3]])
161// CHECK: %[[V14:.*]] = load i8*, i8** %[[V2]], align 8
162// CHECK: call void @_Block_object_dispose(i8* %[[V14]], i32 8)
163// CHECK: call void @llvm.objc.storeStrong(i8** %[[V4]], i8* null)
164// CHECK: br label %[[EH_RESUME:.*]]
165
166// CHECK: [[EH_RESUME]]:
167// CHECK: resume { i8*, i32 }
168
169// CHECK: [[TERMINATE_LPAD]]:
170// CHECK: call void @__clang_call_terminate(
171
172// CHECK-O1-LABEL: define linkonce_odr hidden void @__destroy_helper_block_ea8_32s40r48w56c15_ZTSN5test12S0E60c15_ZTSN5test12S0E(
173// CHECK-O1: call void @llvm.objc.release({{.*}}) {{.*}} !clang.imprecise_release
174// CHECK-O1: call void @llvm.objc.release({{.*}}) {{.*}} !clang.imprecise_release
175// CHECK-NOEXCP: define linkonce_odr hidden void @__destroy_helper_block_8_32s40r48w56c15_ZTSN5test12S0E60c15_ZTSN5test12S0E(
176
177namespace {
178struct TrivialInternal {
179  int a;
180};
181}
182
183struct S0 {
184  S0();
185  S0(const S0 &);
186  ~S0();
187  int f0;
188};
189
190id getObj();
191
192void foo1() {
193  __block id t0 = getObj();
194  __weak id t1 = getObj();
195  id t2 = getObj();
196  S0 t3, t4;
197  // Capturing a non-external type doesn't cause the copy/dispose helpers to be
198  // internal unless the captured type has a non-trivial copy constructor or
199  // destructor.
200  TrivialInternal t5;
201  ^{ (void)t0; (void)t1; (void)t2; (void)t3; (void)t4; (void)t5; };
202}
203}
204
205// Test that calls to @llvm.objc.retainBlock aren't emitted in some cases.
206
207typedef void (^BlockTy)();
208void foo1(id);
209
210namespace test_block_retain {
211
212// CHECK-LABEL: define{{.*}} void @_ZN17test_block_retain14initializationEP11objc_object(
213// CHECK-NOT: @llvm.objc.retainBlock(
214  void initialization(id a) {
215    BlockTy b0 = ^{ foo1(a); };
216    BlockTy b1 = (^{ foo1(a); });
217    b0();
218    b1();
219  }
220
221// CHECK-LABEL: define{{.*}} void @_ZN17test_block_retain20initializationStaticEP11objc_object(
222// CHECK: @llvm.objc.retainBlock(
223  void initializationStatic(id a) {
224    static BlockTy b0 = ^{ foo1(a); };
225    b0();
226  }
227
228// CHECK-LABEL: define{{.*}} void @_ZN17test_block_retain15initialization2EP11objc_object
229// CHECK: %[[B0:.*]] = alloca void ()*, align 8
230// CHECK: %[[B1:.*]] = alloca void ()*, align 8
231// CHECK: load void ()*, void ()** %[[B0]], align 8
232// CHECK-NOT: @llvm.objc.retainBlock
233// CHECK: %[[V9:.*]] = load void ()*, void ()** %[[B0]], align 8
234// CHECK: %[[V10:.*]] = bitcast void ()* %[[V9]] to i8*
235// CHECK: %[[V11:.*]] = call i8* @llvm.objc.retainBlock(i8* %[[V10]])
236// CHECK: %[[V12:.*]] = bitcast i8* %[[V11]] to void ()*
237// CHECK: store void ()* %[[V12]], void ()** %[[B1]], align 8
238  void initialization2(id a) {
239    BlockTy b0 = ^{ foo1(a); };
240    b0();
241    BlockTy b1 = b0; // can't optimize this yet.
242    b1();
243  }
244
245// CHECK-LABEL: define{{.*}} void @_ZN17test_block_retain10assignmentEP11objc_object(
246// CHECK-NOT: @llvm.objc.retainBlock(
247  void assignment(id a) {
248    BlockTy b0;
249    (b0) = ^{ foo1(a); };
250    b0();
251    b0 = (^{ foo1(a); });
252    b0();
253  }
254
255// CHECK-LABEL: define{{.*}} void @_ZN17test_block_retain16assignmentStaticEP11objc_object(
256// CHECK: @llvm.objc.retainBlock(
257  void assignmentStatic(id a) {
258    static BlockTy b0;
259    b0 = ^{ foo1(a); };
260    b0();
261  }
262
263// CHECK-LABEL: define{{.*}} void @_ZN17test_block_retain21assignmentConditionalEP11objc_objectb(
264// CHECK: @llvm.objc.retainBlock(
265  void assignmentConditional(id a, bool c) {
266    BlockTy b0;
267    if (c)
268      // can't optimize this since 'b0' is declared in the outer scope.
269      b0 = ^{ foo1(a); };
270    b0();
271  }
272
273// CHECK-LABEL: define{{.*}} void @_ZN17test_block_retain11assignment2EP11objc_object(
274// CHECK: %[[B0:.*]] = alloca void ()*, align 8
275// CHECK: %[[B1:.*]] = alloca void ()*, align 8
276// CHECK-NOT: @llvm.objc.retainBlock
277// CHECK: store void ()* null, void ()** %[[B1]], align 8
278// CHECK: %[[V9:.*]] = load void ()*, void ()** %[[B0]], align 8
279// CHECK: %[[V10:.*]] = bitcast void ()* %[[V9]] to i8*
280// CHECK: %[[V11:.*]] = call i8* @llvm.objc.retainBlock(i8* %[[V10]]
281// CHECK: %[[V12:.*]] = bitcast i8* %[[V11]] to void ()*
282// CHECK: store void ()* %[[V12]], void ()** %[[B1]], align 8
283  void assignment2(id a) {
284    BlockTy b0 = ^{ foo1(a); };
285    b0();
286    BlockTy b1;
287    b1 = b0; // can't optimize this yet.
288    b1();
289  }
290
291// We cannot remove the call to @llvm.objc.retainBlock if the variable is of type id.
292
293// CHECK: define{{.*}} void @_ZN17test_block_retain21initializationObjCPtrEP11objc_object(
294// CHECK: alloca i8*, align 8
295// CHECK: %[[B0:.*]] = alloca i8*, align 8
296// CHECK: %[[BLOCK:.*]] = alloca <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, align 8
297// CHECK: %[[V3:.*]] = bitcast <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>* %[[BLOCK]] to void ()*
298// CHECK: %[[V4:.*]] = bitcast void ()* %[[V3]] to i8*
299// CHECK: %[[V5:.*]] = call i8* @llvm.objc.retainBlock(i8* %[[V4]])
300// CHECK: %[[V6:.*]] = bitcast i8* %[[V5]] to void ()*
301// CHECK: %[[V7:.*]] = bitcast void ()* %[[V6]] to i8*
302// CHECK: store i8* %[[V7]], i8** %[[B0]], align 8
303  void initializationObjCPtr(id a) {
304    id b0 = ^{ foo1(a); };
305    ((BlockTy)b0)();
306  }
307
308// CHECK: define{{.*}} void @_ZN17test_block_retain17assignmentObjCPtrEP11objc_object(
309// CHECK: %[[B0:.*]] = alloca void ()*, align 8
310// CHECK: %[[B1:.*]] = alloca i8*, align 8
311// CHECK: %[[V4:.*]] = load void ()*, void ()** %[[B0]], align 8
312// CHECK: %[[V5:.*]] = bitcast void ()* %[[V4]] to i8*
313// CHECK: %[[V6:.*]] = call i8* @llvm.objc.retainBlock(i8* %[[V5]])
314// CHECK: %[[V7:.*]] = bitcast i8* %[[V6]] to void ()*
315// CHECK: %[[V8:.*]] = bitcast void ()* %[[V7]] to i8*
316// CHECK: store i8* %[[V8]], i8** %[[B1]], align 8
317  void assignmentObjCPtr(id a) {
318    BlockTy b0 = ^{ foo1(a); };
319    id b1;
320    b1 = b0;
321    ((BlockTy)b1)();
322  }
323}
324
325// Check that the block capture is released after the full expression.
326
327// CHECK-LABEL: define void @_ZN13test_rval_ref4testEP11objc_object(
328// CHECK: %[[BLOCK:.*]] = alloca <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, align 8
329// CHECK: %[[BLOCK_CAPTURED:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>* %[[BLOCK]], i32 0, i32 5
330// CHECK: %[[V1:.*]] = call i8* @llvm.objc.retain(
331// CHECK: store i8* %[[V1]], i8** %[[BLOCK_CAPTURED]], align 8
332// CHECK: invoke void @_ZN13test_rval_ref17callTemplateBlockEOU15__autoreleasingU13block_pointerFvvE(
333
334// CHECK: call void @llvm.objc.storeStrong(i8** %[[BLOCK_CAPTURED]], i8* null)
335
336namespace test_rval_ref {
337  void callTemplateBlock(BlockTy &&func);
338
339  void test(id str) {
340    return callTemplateBlock(^void() {
341      foo1(str);
342    });
343  }
344}
345