1// RUN: %clang_cc1 %s -fblocks -triple x86_64-apple-darwin -emit-llvm -o - | FileCheck %s
2
3namespace test0 {
4  // CHECK-LABEL: define void @_ZN5test04testEi(
5  // CHECK: define internal void @___ZN5test04testEi_block_invoke{{.*}}(
6  // CHECK: define internal void @___ZN5test04testEi_block_invoke_2{{.*}}(
7  void test(int x) {
8    ^{ ^{ (void) x; }; };
9  }
10}
11
12extern void (^out)();
13
14namespace test1 {
15  // Capturing const objects doesn't require a local block.
16  // CHECK-LABEL: define void @_ZN5test15test1Ev()
17  // CHECK:   store void ()* bitcast ({{.*}} @__block_literal_global{{.*}} to void ()*), void ()** @out
18  void test1() {
19    const int NumHorsemen = 4;
20    out = ^{ (void) NumHorsemen; };
21  }
22
23  // That applies to structs too...
24  // CHECK-LABEL: define void @_ZN5test15test2Ev()
25  // CHECK:   store void ()* bitcast ({{.*}} @__block_literal_global{{.*}} to void ()*), void ()** @out
26  struct loc { double x, y; };
27  void test2() {
28    const loc target = { 5, 6 };
29    out = ^{ (void) target; };
30  }
31
32  // ...unless they have mutable fields...
33  // CHECK-LABEL: define void @_ZN5test15test3Ev()
34  // CHECK:   [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
35  // CHECK:   [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to void ()*
36  // CHECK:   store void ()* [[T0]], void ()** @out
37  struct mut { mutable int x; };
38  void test3() {
39    const mut obj = { 5 };
40    out = ^{ (void) obj; };
41  }
42
43  // ...or non-trivial destructors...
44  // CHECK-LABEL: define void @_ZN5test15test4Ev()
45  // CHECK:   [[OBJ:%.*]] = alloca
46  // CHECK:   [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
47  // CHECK:   [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to void ()*
48  // CHECK:   store void ()* [[T0]], void ()** @out
49  struct scope { int x; ~scope(); };
50  void test4() {
51    const scope obj = { 5 };
52    out = ^{ (void) obj; };
53  }
54
55  // ...or non-trivial copy constructors, but it's not clear how to do
56  // that and still have a constant initializer in '03.
57}
58
59namespace test2 {
60  struct A {
61    A();
62    A(const A &);
63    ~A();
64  };
65
66  struct B {
67    B();
68    B(const B &);
69    ~B();
70  };
71
72  // CHECK-LABEL: define void @_ZN5test24testEv()
73  void test() {
74    __block A a;
75    __block B b;
76  }
77
78  // CHECK-LABEL: define internal void @__Block_byref_object_copy
79  // CHECK: call void @_ZN5test21AC1ERKS0_(
80
81  // CHECK-LABEL: define internal void @__Block_byref_object_dispose
82  // CHECK: call void @_ZN5test21AD1Ev(
83
84  // CHECK-LABEL: define internal void @__Block_byref_object_copy
85  // CHECK: call void @_ZN5test21BC1ERKS0_(
86
87  // CHECK-LABEL: define internal void @__Block_byref_object_dispose
88  // CHECK: call void @_ZN5test21BD1Ev(
89}
90
91// rdar://problem/9334739
92// Make sure we mark destructors for parameters captured in blocks.
93namespace test3 {
94  struct A {
95    A(const A&);
96    ~A();
97  };
98
99  struct B : A {
100  };
101
102  void test(B b) {
103    extern void consume(void(^)());
104    consume(^{ (void) b; });
105  }
106}
107
108// rdar://problem/9971485
109namespace test4 {
110  struct A {
111    A();
112    ~A();
113  };
114
115  void foo(A a);
116
117  void test() {
118    extern void consume(void(^)());
119    consume(^{ return foo(A()); });
120  }
121  // CHECK-LABEL: define void @_ZN5test44testEv()
122  // CHECK-LABEL: define internal void @___ZN5test44testEv_block_invoke
123  // CHECK: [[TMP:%.*]] = alloca [[A:%.*]], align 1
124  // CHECK-NEXT: store i8* [[BLOCKDESC:%.*]], i8** {{.*}}, align 8
125  // CHECK-NEXT: load i8*
126  // CHECK-NEXT: bitcast i8* [[BLOCKDESC]] to <{ i8*, i32, i32, i8*, %struct.__block_descriptor* }>*
127  // CHECK:      call void @_ZN5test41AC1Ev([[A]]* [[TMP]])
128  // CHECK-NEXT: call void @_ZN5test43fooENS_1AE([[A]]* [[TMP]])
129  // CHECK-NEXT: call void @_ZN5test41AD1Ev([[A]]* [[TMP]])
130  // CHECK-NEXT: ret void
131}
132
133namespace test5 {
134  struct A {
135    unsigned afield;
136    A();
137    A(const A&);
138    ~A();
139    void foo() const;
140  };
141
142  void doWithBlock(void(^)());
143
144  void test(bool cond) {
145    A x;
146    void (^b)() = (cond ? ^{ x.foo(); } : (void(^)()) 0);
147    doWithBlock(b);
148  }
149
150  // CHECK-LABEL:    define void @_ZN5test54testEb(
151  // CHECK:      [[COND:%.*]] = alloca i8
152  // CHECK-NEXT: [[X:%.*]] = alloca [[A:%.*]], align 4
153  // CHECK-NEXT: [[B:%.*]] = alloca void ()*, align 8
154  // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:.*]], align 8
155  // CHECK-NEXT: [[CLEANUP_ACTIVE:%.*]] = alloca i1
156  // CHECK-NEXT: [[T0:%.*]] = zext i1
157  // CHECK-NEXT: store i8 [[T0]], i8* [[COND]], align 1
158  // CHECK-NEXT: call void @_ZN5test51AC1Ev([[A]]* [[X]])
159  // CHECK-NEXT: [[CLEANUP_ADDR:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
160  // CHECK-NEXT: [[T0:%.*]] = load i8* [[COND]], align 1
161  // CHECK-NEXT: [[T1:%.*]] = trunc i8 [[T0]] to i1
162  // CHECK-NEXT: store i1 false, i1* [[CLEANUP_ACTIVE]]
163  // CHECK-NEXT: br i1 [[T1]],
164
165  // CHECK-NOT:  br
166  // CHECK:      [[CAPTURE:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
167  // CHECK-NEXT: call void @_ZN5test51AC1ERKS0_([[A]]* [[CAPTURE]], [[A]]* nonnull [[X]])
168  // CHECK-NEXT: store i1 true, i1* [[CLEANUP_ACTIVE]]
169  // CHECK-NEXT: bitcast [[BLOCK_T]]* [[BLOCK]] to void ()*
170  // CHECK-NEXT: br label
171  // CHECK:      br label
172  // CHECK:      phi
173  // CHECK-NEXT: store
174  // CHECK-NEXT: load
175  // CHECK-NEXT: call void @_ZN5test511doWithBlockEU13block_pointerFvvE(
176  // CHECK-NEXT: [[T0:%.*]] = load i1* [[CLEANUP_ACTIVE]]
177  // CHECK-NEXT: br i1 [[T0]]
178  // CHECK:      call void @_ZN5test51AD1Ev([[A]]* [[CLEANUP_ADDR]])
179  // CHECK-NEXT: br label
180  // CHECK:      call void @_ZN5test51AD1Ev([[A]]* [[X]])
181  // CHECK-NEXT: ret void
182}
183
184namespace test6 {
185  struct A {
186    A();
187    ~A();
188  };
189
190  void foo(const A &, void (^)());
191  void bar();
192
193  void test() {
194    // Make sure that the temporary cleanup isn't somehow captured
195    // within the block.
196    foo(A(), ^{ bar(); });
197    bar();
198  }
199
200  // CHECK-LABEL:    define void @_ZN5test64testEv()
201  // CHECK:      [[TEMP:%.*]] = alloca [[A:%.*]], align 1
202  // CHECK-NEXT: call void @_ZN5test61AC1Ev([[A]]* [[TEMP]])
203  // CHECK-NEXT: call void @_ZN5test63fooERKNS_1AEU13block_pointerFvvE(
204  // CHECK-NEXT: call void @_ZN5test61AD1Ev([[A]]* [[TEMP]])
205  // CHECK-NEXT: call void @_ZN5test63barEv()
206  // CHECK-NEXT: ret void
207}
208
209namespace test7 {
210  int f() {
211    static int n;
212    int *const p = &n;
213    return ^{ return *p; }();
214  }
215}
216
217namespace test8 {
218  // <rdar://problem/10832617>: failure to capture this after skipping rebuild
219  // of the 'this' pointer.
220  struct X {
221    int x;
222
223    template<typename T>
224    int foo() {
225      return ^ { return x; }();
226    }
227  };
228
229  template int X::foo<int>();
230}
231
232// rdar://13459289
233namespace test9 {
234  struct B {
235    void *p;
236    B();
237    B(const B&);
238    ~B();
239  };
240
241  void use_block(void (^)());
242  void use_block_2(void (^)(), const B &a);
243
244  // Ensuring that creating a non-trivial capture copy expression
245  // doesn't end up stealing the block registration for the block we
246  // just parsed.  That block must have captures or else it won't
247  // force registration.  Must occur within a block for some reason.
248  void test() {
249    B x;
250    use_block(^{
251        int y;
252        use_block_2(^{ (void)y; }, x);
253    });
254  }
255}
256