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