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