blocks.cpp revision 9cbe4f0ba01ec304e1e3d071c071f7bca33631c0
1// RUN: %clang_cc1 %s -fblocks -triple x86_64-apple-darwin -emit-llvm -o - | FileCheck %s
2
3namespace test0 {
4  // CHECK: define void @_ZN5test04testEi(
5  // CHECK: define internal void @__test_block_invoke_{{.*}}(
6  // CHECK: define internal void @__block_global_{{.*}}(
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: 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: 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: 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: 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: define void @_ZN5test24testEv()
73  void test() {
74    __block A a;
75    __block B b;
76  }
77
78  // CHECK: define internal void @__Block_byref_object_copy
79  // CHECK: call void @_ZN5test21AC1ERKS0_(
80
81  // CHECK: define internal void @__Block_byref_object_dispose
82  // CHECK: call void @_ZN5test21AD1Ev(
83
84  // CHECK: define internal void @__Block_byref_object_copy
85  // CHECK: call void @_ZN5test21BC1ERKS0_(
86
87  // CHECK: 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