blocks.cpp revision b99785bdd1cc9ce1ba4f94eeb871faba1a22e95f
1bb699b07426be017056c2c549ac3ffb488cab6e3John McCall// RUN: %clang_cc1 %s -fblocks -triple x86_64-apple-darwin -emit-llvm -o - | FileCheck %s
2bb699b07426be017056c2c549ac3ffb488cab6e3John McCall
3bb699b07426be017056c2c549ac3ffb488cab6e3John McCallnamespace test0 {
4bb699b07426be017056c2c549ac3ffb488cab6e3John McCall  // CHECK: define void @_ZN5test04testEi(
5bb699b07426be017056c2c549ac3ffb488cab6e3John McCall  // CHECK: define internal void @__test_block_invoke_{{.*}}(
6bb699b07426be017056c2c549ac3ffb488cab6e3John McCall  // CHECK: define internal void @__block_global_{{.*}}(
7bb699b07426be017056c2c549ac3ffb488cab6e3John McCall  void test(int x) {
8bb699b07426be017056c2c549ac3ffb488cab6e3John McCall    ^{ ^{ (void) x; }; };
9bb699b07426be017056c2c549ac3ffb488cab6e3John McCall  }
10bb699b07426be017056c2c549ac3ffb488cab6e3John McCall}
11461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall
12461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCallextern void (^out)();
13461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall
14461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCallnamespace test1 {
15461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall  // Capturing const objects doesn't require a local block.
16461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall  // CHECK: define void @_ZN5test15test1Ev()
17461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall  // CHECK:   store void ()* bitcast ({{.*}} @__block_literal_global{{.*}} to void ()*), void ()** @out
18461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall  void test1() {
19461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall    const int NumHorsemen = 4;
20461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall    out = ^{ (void) NumHorsemen; };
21461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall  }
22461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall
23461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall  // That applies to structs too...
24461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall  // CHECK: define void @_ZN5test15test2Ev()
25461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall  // CHECK:   store void ()* bitcast ({{.*}} @__block_literal_global{{.*}} to void ()*), void ()** @out
26461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall  struct loc { double x, y; };
27461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall  void test2() {
28461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall    const loc target = { 5, 6 };
29461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall    out = ^{ (void) target; };
30461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall  }
31461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall
32461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall  // ...unless they have mutable fields...
33461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall  // CHECK: define void @_ZN5test15test3Ev()
349cbe4f0ba01ec304e1e3d071c071f7bca33631c0Chris Lattner  // CHECK:   [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
35461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall  // CHECK:   [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to void ()*
36461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall  // CHECK:   store void ()* [[T0]], void ()** @out
37461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall  struct mut { mutable int x; };
38461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall  void test3() {
39461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall    const mut obj = { 5 };
40461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall    out = ^{ (void) obj; };
41461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall  }
42461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall
43461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall  // ...or non-trivial destructors...
44461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall  // CHECK: define void @_ZN5test15test4Ev()
45461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall  // CHECK:   [[OBJ:%.*]] = alloca
469cbe4f0ba01ec304e1e3d071c071f7bca33631c0Chris Lattner  // CHECK:   [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
47461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall  // CHECK:   [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to void ()*
48461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall  // CHECK:   store void ()* [[T0]], void ()** @out
49461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall  struct scope { int x; ~scope(); };
50461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall  void test4() {
51461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall    const scope obj = { 5 };
52461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall    out = ^{ (void) obj; };
53461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall  }
54461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall
55461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall  // ...or non-trivial copy constructors, but it's not clear how to do
56461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall  // that and still have a constant initializer in '03.
57461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall}
58f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall
59f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCallnamespace test2 {
60f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall  struct A {
61f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall    A();
62f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall    A(const A &);
63f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall    ~A();
64f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall  };
65f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall
66f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall  struct B {
67f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall    B();
68f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall    B(const B &);
69f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall    ~B();
70f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall  };
71f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall
72f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall  // CHECK: define void @_ZN5test24testEv()
73f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall  void test() {
74f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall    __block A a;
75f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall    __block B b;
76f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall  }
77f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall
78f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall  // CHECK: define internal void @__Block_byref_object_copy
79f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall  // CHECK: call void @_ZN5test21AC1ERKS0_(
80f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall
81f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall  // CHECK: define internal void @__Block_byref_object_dispose
82f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall  // CHECK: call void @_ZN5test21AD1Ev(
83f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall
84f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall  // CHECK: define internal void @__Block_byref_object_copy
85f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall  // CHECK: call void @_ZN5test21BC1ERKS0_(
86f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall
87f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall  // CHECK: define internal void @__Block_byref_object_dispose
88f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall  // CHECK: call void @_ZN5test21BD1Ev(
89f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall}
90642a75f883e644bcfbb82e7af0313776ad1ce33cJohn McCall
91642a75f883e644bcfbb82e7af0313776ad1ce33cJohn McCall// rdar://problem/9334739
92642a75f883e644bcfbb82e7af0313776ad1ce33cJohn McCall// Make sure we mark destructors for parameters captured in blocks.
93642a75f883e644bcfbb82e7af0313776ad1ce33cJohn McCallnamespace test3 {
94642a75f883e644bcfbb82e7af0313776ad1ce33cJohn McCall  struct A {
95642a75f883e644bcfbb82e7af0313776ad1ce33cJohn McCall    A(const A&);
96642a75f883e644bcfbb82e7af0313776ad1ce33cJohn McCall    ~A();
97642a75f883e644bcfbb82e7af0313776ad1ce33cJohn McCall  };
98642a75f883e644bcfbb82e7af0313776ad1ce33cJohn McCall
99642a75f883e644bcfbb82e7af0313776ad1ce33cJohn McCall  struct B : A {
100642a75f883e644bcfbb82e7af0313776ad1ce33cJohn McCall  };
101642a75f883e644bcfbb82e7af0313776ad1ce33cJohn McCall
102642a75f883e644bcfbb82e7af0313776ad1ce33cJohn McCall  void test(B b) {
103642a75f883e644bcfbb82e7af0313776ad1ce33cJohn McCall    extern void consume(void(^)());
104642a75f883e644bcfbb82e7af0313776ad1ce33cJohn McCall    consume(^{ (void) b; });
105642a75f883e644bcfbb82e7af0313776ad1ce33cJohn McCall  }
106642a75f883e644bcfbb82e7af0313776ad1ce33cJohn McCall}
107d963c37eb912342c8325048749e449861cf0a6e3John McCall
108d963c37eb912342c8325048749e449861cf0a6e3John McCall// rdar://problem/9971485
109d963c37eb912342c8325048749e449861cf0a6e3John McCallnamespace test4 {
110d963c37eb912342c8325048749e449861cf0a6e3John McCall  struct A {
111d963c37eb912342c8325048749e449861cf0a6e3John McCall    A();
112d963c37eb912342c8325048749e449861cf0a6e3John McCall    ~A();
113d963c37eb912342c8325048749e449861cf0a6e3John McCall  };
114d963c37eb912342c8325048749e449861cf0a6e3John McCall
115d963c37eb912342c8325048749e449861cf0a6e3John McCall  void foo(A a);
116d963c37eb912342c8325048749e449861cf0a6e3John McCall
117d963c37eb912342c8325048749e449861cf0a6e3John McCall  void test() {
118d963c37eb912342c8325048749e449861cf0a6e3John McCall    extern void consume(void(^)());
119d963c37eb912342c8325048749e449861cf0a6e3John McCall    consume(^{ return foo(A()); });
120d963c37eb912342c8325048749e449861cf0a6e3John McCall  }
121d963c37eb912342c8325048749e449861cf0a6e3John McCall  // CHECK: define void @_ZN5test44testEv()
122d963c37eb912342c8325048749e449861cf0a6e3John McCall  // CHECK: define internal void @__test_block_invoke
123d963c37eb912342c8325048749e449861cf0a6e3John McCall  // CHECK:      [[TMP:%.*]] = alloca [[A:%.*]], align 1
124d963c37eb912342c8325048749e449861cf0a6e3John McCall  // CHECK-NEXT: bitcast i8*
125d963c37eb912342c8325048749e449861cf0a6e3John McCall  // CHECK-NEXT: call void @_ZN5test41AC1Ev([[A]]* [[TMP]])
126d963c37eb912342c8325048749e449861cf0a6e3John McCall  // CHECK-NEXT: call void @_ZN5test43fooENS_1AE([[A]]* [[TMP]])
127d963c37eb912342c8325048749e449861cf0a6e3John McCall  // CHECK-NEXT: call void @_ZN5test41AD1Ev([[A]]* [[TMP]])
128d963c37eb912342c8325048749e449861cf0a6e3John McCall  // CHECK-NEXT: ret void
129d963c37eb912342c8325048749e449861cf0a6e3John McCall}
130d963c37eb912342c8325048749e449861cf0a6e3John McCall
131b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCallnamespace test5 {
132b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall  struct A {
133b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall    unsigned afield;
134b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall    A();
135b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall    A(const A&);
136b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall    ~A();
137b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall    void foo() const;
138b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall  };
139b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall
140b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall  void doWithBlock(void(^)());
141b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall
142b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall  void test(bool cond) {
143b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall    A x;
144b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall    void (^b)() = (cond ? ^{ x.foo(); } : (void(^)()) 0);
145b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall    doWithBlock(b);
146b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall  }
147b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall
148b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall  // CHECK:    define void @_ZN5test54testEb(
149b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall  // CHECK:      [[COND:%.*]] = alloca i8
150b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall  // CHECK-NEXT: [[X:%.*]] = alloca [[A:%.*]], align 4
151b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall  // CHECK-NEXT: [[B:%.*]] = alloca void ()*, align 8
152b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall  // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:.*]], align 8
153b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall  // CHECK-NEXT: [[CLEANUP_ACTIVE:%.*]] = alloca i1
154b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall  // CHECK-NEXT: store i1 false, i1* [[CLEANUP_ACTIVE]]
155b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall  // CHECK-NEXT: [[T0:%.*]] = zext i1
156b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall  // CHECK-NEXT: store i8 [[T0]], i8* [[COND]], align 1
157b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall  // CHECK-NEXT: call void @_ZN5test51AC1Ev([[A]]* [[X]])
158b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall  // CHECK-NEXT: [[CLEANUP_ADDR:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
159b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall  // CHECK-NEXT: [[T0:%.*]] = load i8* [[COND]], align 1
160b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall  // CHECK-NEXT: [[T1:%.*]] = trunc i8 [[T0]] to i1
161b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall  // CHECK-NEXT: br i1 [[T1]],
162b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall
163b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall  // CHECK-NOT:  br
164b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall  // CHECK:      [[CAPTURE:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
165b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall  // CHECK-NEXT: call void @_ZN5test51AC1ERKS0_([[A]]* [[CAPTURE]], [[A]]* [[X]])
166b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall  // CHECK-NEXT: store i1 true, i1* [[CLEANUP_ACTIVE]]
167b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall  // CHECK-NEXT: bitcast [[BLOCK_T]]* [[BLOCK]] to void ()*
168b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall  // CHECK-NEXT: br label
169b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall  // CHECK:      br label
170b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall  // CHECK:      phi
171b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall  // CHECK-NEXT: store
172b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall  // CHECK-NEXT: load
173b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall  // CHECK-NEXT: call void @_ZN5test511doWithBlockEU13block_pointerFvvE(
174b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall  // CHECK-NEXT: [[T0:%.*]] = load i1* [[CLEANUP_ACTIVE]]
175b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall  // CHECK-NEXT: br i1 [[T0]]
176b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall  // CHECK:      call void @_ZN5test51AD1Ev([[A]]* [[CLEANUP_ADDR]])
177b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall  // CHECK-NEXT: br label
178b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall  // CHECK:      call void @_ZN5test51AD1Ev([[A]]* [[X]])
179b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall  // CHECK-NEXT: ret void
180b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall}
181