1 // RUN: %clang_cc1 %s -fblocks -triple x86_64-apple-darwin -emit-llvm -o - | FileCheck %s 2 3 namespace test0 { 4 // CHECK-LABEL: define void @_ZN5test04testEi( 5 // CHECK: define internal void @___ZN5test04testEi_block_invoke{{.*}}( 6 // CHECK: define internal void @___ZN5test04testEi_block_invoke_2{{.*}}( test(int x)7 void test(int x) { 8 ^{ ^{ (void) x; }; }; 9 } 10 } 11 12 extern void (^out)(); 13 14 namespace 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 test1()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; }; test2()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; }; test3()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(); }; test4()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 59 namespace 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() test()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. 93 namespace test3 { 94 struct A { 95 A(const A&); 96 ~A(); 97 }; 98 99 struct B : A { 100 }; 101 test(B b)102 void test(B b) { 103 extern void consume(void(^)()); 104 consume(^{ (void) b; }); 105 } 106 } 107 108 // rdar://problem/9971485 109 namespace test4 { 110 struct A { 111 A(); 112 ~A(); 113 }; 114 115 void foo(A a); 116 test()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*, 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 133 namespace 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 test(bool cond)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_T]]* [[BLOCK]], i32 0, i32 5 160 // CHECK-NEXT: [[T0:%.*]] = load i8, 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_T]]* [[BLOCK]], i32 0, i32 5 167 // CHECK-NEXT: call void @_ZN5test51AC1ERKS0_([[A]]* [[CAPTURE]], [[A]]* dereferenceable({{[0-9]+}}) [[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, 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 184 namespace test6 { 185 struct A { 186 A(); 187 ~A(); 188 }; 189 190 void foo(const A &, void (^)()); 191 void bar(); 192 test()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 209 namespace test7 { f()210 int f() { 211 static int n; 212 int *const p = &n; 213 return ^{ return *p; }(); 214 } 215 } 216 217 namespace 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> footest8::X224 int foo() { 225 return ^ { return x; }(); 226 } 227 }; 228 229 template int X::foo<int>(); 230 } 231 232 // rdar://13459289 233 namespace 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. test()248 void test() { 249 B x; 250 use_block(^{ 251 int y; 252 use_block_2(^{ (void)y; }, x); 253 }); 254 } 255 } 256