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