1*f4a2713aSLionel Sambuc // RUN: %clang_cc1 %s -fblocks -triple x86_64-apple-darwin -std=c++11 -emit-llvm -o - | FileCheck %s 2*f4a2713aSLionel Sambuc 3*f4a2713aSLionel Sambuc template <class T> void takeItByValue(T); 4*f4a2713aSLionel Sambuc void takeABlock(void (^)()); 5*f4a2713aSLionel Sambuc 6*f4a2713aSLionel Sambuc // rdar://problem/11022704 7*f4a2713aSLionel Sambuc namespace test_int { 8*f4a2713aSLionel Sambuc void test() { 9*f4a2713aSLionel Sambuc const int x = 100; 10*f4a2713aSLionel Sambuc takeABlock(^{ takeItByValue(x); }); 11*f4a2713aSLionel Sambuc // CHECK: call void @_Z13takeItByValueIiEvT_(i32 100) 12*f4a2713aSLionel Sambuc } 13*f4a2713aSLionel Sambuc } 14*f4a2713aSLionel Sambuc 15*f4a2713aSLionel Sambuc namespace test_int_ref { 16*f4a2713aSLionel Sambuc void test() { 17*f4a2713aSLionel Sambuc const int y = 200; 18*f4a2713aSLionel Sambuc const int &x = y; 19*f4a2713aSLionel Sambuc takeABlock(^{ takeItByValue(x); }); 20*f4a2713aSLionel Sambuc 21*f4a2713aSLionel Sambuc // TODO: there's no good reason that this isn't foldable. 22*f4a2713aSLionel Sambuc // CHECK: call void @_Z13takeItByValueIiEvT_(i32 {{%.*}}) 23*f4a2713aSLionel Sambuc } 24*f4a2713aSLionel Sambuc } 25*f4a2713aSLionel Sambuc 26*f4a2713aSLionel Sambuc namespace test_float { 27*f4a2713aSLionel Sambuc void test() { 28*f4a2713aSLionel Sambuc const float x = 1; 29*f4a2713aSLionel Sambuc takeABlock(^{ takeItByValue(x); }); 30*f4a2713aSLionel Sambuc // CHECK: call void @_Z13takeItByValueIfEvT_(float 1.0 31*f4a2713aSLionel Sambuc } 32*f4a2713aSLionel Sambuc } 33*f4a2713aSLionel Sambuc 34*f4a2713aSLionel Sambuc namespace test_float_ref { 35*f4a2713aSLionel Sambuc void test() { 36*f4a2713aSLionel Sambuc const float y = 100; 37*f4a2713aSLionel Sambuc const float &x = y; 38*f4a2713aSLionel Sambuc takeABlock(^{ takeItByValue(x); }); 39*f4a2713aSLionel Sambuc 40*f4a2713aSLionel Sambuc // TODO: there's no good reason that this isn't foldable. 41*f4a2713aSLionel Sambuc // CHECK: call void @_Z13takeItByValueIfEvT_(float {{%.*}}) 42*f4a2713aSLionel Sambuc } 43*f4a2713aSLionel Sambuc } 44*f4a2713aSLionel Sambuc 45*f4a2713aSLionel Sambuc namespace test_complex_int { 46*f4a2713aSLionel Sambuc void test() { 47*f4a2713aSLionel Sambuc constexpr _Complex int x = 500; 48*f4a2713aSLionel Sambuc takeABlock(^{ takeItByValue(x); }); 49*f4a2713aSLionel Sambuc // CHECK: store { i32, i32 } { i32 500, i32 0 }, 50*f4a2713aSLionel Sambuc 51*f4a2713aSLionel Sambuc // CHECK: store i32 500, 52*f4a2713aSLionel Sambuc // CHECK-NEXT: store i32 0, 53*f4a2713aSLionel Sambuc // CHECK-NEXT: [[COERCE:%.*]] = bitcast 54*f4a2713aSLionel Sambuc // CHECK-NEXT: [[CVAL:%.*]] = load i64* [[COERCE]] 55*f4a2713aSLionel Sambuc // CHECK-NEXT: call void @_Z13takeItByValueICiEvT_(i64 [[CVAL]]) 56*f4a2713aSLionel Sambuc } 57*f4a2713aSLionel Sambuc } 58*f4a2713aSLionel Sambuc 59*f4a2713aSLionel Sambuc namespace test_complex_int_ref { 60*f4a2713aSLionel Sambuc void test() { 61*f4a2713aSLionel Sambuc const _Complex int y = 100; 62*f4a2713aSLionel Sambuc const _Complex int &x = y; 63*f4a2713aSLionel Sambuc takeABlock(^{ takeItByValue(x); }); 64*f4a2713aSLionel Sambuc // CHECK: call void @_Z13takeItByValueICiEvT_(i64 65*f4a2713aSLionel Sambuc } 66*f4a2713aSLionel Sambuc } 67*f4a2713aSLionel Sambuc 68*f4a2713aSLionel Sambuc namespace test_complex_int_ref_mutable { 69*f4a2713aSLionel Sambuc _Complex int y = 100; 70*f4a2713aSLionel Sambuc void test() { 71*f4a2713aSLionel Sambuc const _Complex int &x = y; 72*f4a2713aSLionel Sambuc takeABlock(^{ takeItByValue(x); }); 73*f4a2713aSLionel Sambuc // CHECK: [[R:%.*]] = load i32* getelementptr inbounds ({ i32, i32 }* @_ZN28test_complex_int_ref_mutable1yE, i32 0, i32 0) 74*f4a2713aSLionel Sambuc // CHECK-NEXT: [[I:%.*]] = load i32* getelementptr inbounds ({ i32, i32 }* @_ZN28test_complex_int_ref_mutable1yE, i32 0, i32 1) 75*f4a2713aSLionel Sambuc // CHECK-NEXT: [[RSLOT:%.*]] = getelementptr inbounds { i32, i32 }* [[CSLOT:%.*]], i32 0, i32 0 76*f4a2713aSLionel Sambuc // CHECK-NEXT: [[ISLOT:%.*]] = getelementptr inbounds { i32, i32 }* [[CSLOT]], i32 0, i32 1 77*f4a2713aSLionel Sambuc // CHECK-NEXT: store i32 [[R]], i32* [[RSLOT]] 78*f4a2713aSLionel Sambuc // CHECK-NEXT: store i32 [[I]], i32* [[ISLOT]] 79*f4a2713aSLionel Sambuc // CHECK-NEXT: [[COERCE:%.*]] = bitcast { i32, i32 }* [[CSLOT]] to i64* 80*f4a2713aSLionel Sambuc // CHECK-NEXT: [[CVAL:%.*]] = load i64* [[COERCE]], 81*f4a2713aSLionel Sambuc // CHECK-NEXT: call void @_Z13takeItByValueICiEvT_(i64 [[CVAL]]) 82*f4a2713aSLionel Sambuc } 83*f4a2713aSLionel Sambuc } 84*f4a2713aSLionel Sambuc 85*f4a2713aSLionel Sambuc // rdar://13295759 86*f4a2713aSLionel Sambuc namespace test_block_in_lambda { 87*f4a2713aSLionel Sambuc void takeBlock(void (^block)()); 88*f4a2713aSLionel Sambuc 89*f4a2713aSLionel Sambuc // The captured variable has to be non-POD so that we have a copy expression. 90*f4a2713aSLionel Sambuc struct A { 91*f4a2713aSLionel Sambuc void *p; 92*f4a2713aSLionel Sambuc A(const A &); 93*f4a2713aSLionel Sambuc ~A(); 94*f4a2713aSLionel Sambuc void use() const; 95*f4a2713aSLionel Sambuc }; 96*f4a2713aSLionel Sambuc 97*f4a2713aSLionel Sambuc void test(A a) { 98*f4a2713aSLionel Sambuc auto lambda = [a]() { 99*f4a2713aSLionel Sambuc takeBlock(^{ a.use(); }); 100*f4a2713aSLionel Sambuc }; 101*f4a2713aSLionel Sambuc lambda(); // make sure we emit the invocation function 102*f4a2713aSLionel Sambuc } 103*f4a2713aSLionel Sambuc // CHECK-LABEL: define internal void @"_ZZN20test_block_in_lambda4testENS_1AEENK3$_0clEv"( 104*f4a2713aSLionel Sambuc // CHECK: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]], align 8 105*f4a2713aSLionel Sambuc // CHECK: [[THIS:%.*]] = load [[LAMBDA_T:%.*]]** 106*f4a2713aSLionel Sambuc // CHECK: [[TO_DESTROY:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 107*f4a2713aSLionel Sambuc // CHECK: [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 108*f4a2713aSLionel Sambuc // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[LAMBDA_T]]* [[THIS]], i32 0, i32 0 109*f4a2713aSLionel Sambuc // CHECK-NEXT: call void @_ZN20test_block_in_lambda1AC1ERKS0_({{.*}}* [[T0]], {{.*}}* [[T1]]) 110*f4a2713aSLionel Sambuc // CHECK-NEXT: [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to void ()* 111*f4a2713aSLionel Sambuc // CHECK-NEXT: call void @_ZN20test_block_in_lambda9takeBlockEU13block_pointerFvvE(void ()* [[T0]]) 112*f4a2713aSLionel Sambuc // CHECK-NEXT: call void @_ZN20test_block_in_lambda1AD1Ev({{.*}}* [[TO_DESTROY]]) 113*f4a2713aSLionel Sambuc // CHECK-NEXT: ret void 114*f4a2713aSLionel Sambuc } 115