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