blocks.cpp revision b99785bdd1cc9ce1ba4f94eeb871faba1a22e95f
1bb699b07426be017056c2c549ac3ffb488cab6e3John McCall// RUN: %clang_cc1 %s -fblocks -triple x86_64-apple-darwin -emit-llvm -o - | FileCheck %s 2bb699b07426be017056c2c549ac3ffb488cab6e3John McCall 3bb699b07426be017056c2c549ac3ffb488cab6e3John McCallnamespace test0 { 4bb699b07426be017056c2c549ac3ffb488cab6e3John McCall // CHECK: define void @_ZN5test04testEi( 5bb699b07426be017056c2c549ac3ffb488cab6e3John McCall // CHECK: define internal void @__test_block_invoke_{{.*}}( 6bb699b07426be017056c2c549ac3ffb488cab6e3John McCall // CHECK: define internal void @__block_global_{{.*}}( 7bb699b07426be017056c2c549ac3ffb488cab6e3John McCall void test(int x) { 8bb699b07426be017056c2c549ac3ffb488cab6e3John McCall ^{ ^{ (void) x; }; }; 9bb699b07426be017056c2c549ac3ffb488cab6e3John McCall } 10bb699b07426be017056c2c549ac3ffb488cab6e3John McCall} 11461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall 12461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCallextern void (^out)(); 13461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall 14461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCallnamespace test1 { 15461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall // Capturing const objects doesn't require a local block. 16461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall // CHECK: define void @_ZN5test15test1Ev() 17461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall // CHECK: store void ()* bitcast ({{.*}} @__block_literal_global{{.*}} to void ()*), void ()** @out 18461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall void test1() { 19461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall const int NumHorsemen = 4; 20461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall out = ^{ (void) NumHorsemen; }; 21461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall } 22461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall 23461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall // That applies to structs too... 24461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall // CHECK: define void @_ZN5test15test2Ev() 25461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall // CHECK: store void ()* bitcast ({{.*}} @__block_literal_global{{.*}} to void ()*), void ()** @out 26461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall struct loc { double x, y; }; 27461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall void test2() { 28461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall const loc target = { 5, 6 }; 29461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall out = ^{ (void) target; }; 30461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall } 31461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall 32461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall // ...unless they have mutable fields... 33461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall // CHECK: define void @_ZN5test15test3Ev() 349cbe4f0ba01ec304e1e3d071c071f7bca33631c0Chris Lattner // CHECK: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]], 35461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall // CHECK: [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to void ()* 36461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall // CHECK: store void ()* [[T0]], void ()** @out 37461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall struct mut { mutable int x; }; 38461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall void test3() { 39461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall const mut obj = { 5 }; 40461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall out = ^{ (void) obj; }; 41461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall } 42461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall 43461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall // ...or non-trivial destructors... 44461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall // CHECK: define void @_ZN5test15test4Ev() 45461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall // CHECK: [[OBJ:%.*]] = alloca 469cbe4f0ba01ec304e1e3d071c071f7bca33631c0Chris Lattner // CHECK: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]], 47461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall // CHECK: [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to void ()* 48461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall // CHECK: store void ()* [[T0]], void ()** @out 49461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall struct scope { int x; ~scope(); }; 50461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall void test4() { 51461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall const scope obj = { 5 }; 52461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall out = ^{ (void) obj; }; 53461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall } 54461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall 55461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall // ...or non-trivial copy constructors, but it's not clear how to do 56461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall // that and still have a constant initializer in '03. 57461c9c1bc39ed8cbe8311f396f7ee3839e9fda53John McCall} 58f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall 59f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCallnamespace test2 { 60f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall struct A { 61f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall A(); 62f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall A(const A &); 63f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall ~A(); 64f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall }; 65f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall 66f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall struct B { 67f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall B(); 68f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall B(const B &); 69f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall ~B(); 70f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall }; 71f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall 72f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall // CHECK: define void @_ZN5test24testEv() 73f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall void test() { 74f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall __block A a; 75f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall __block B b; 76f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall } 77f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall 78f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall // CHECK: define internal void @__Block_byref_object_copy 79f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall // CHECK: call void @_ZN5test21AC1ERKS0_( 80f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall 81f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall // CHECK: define internal void @__Block_byref_object_dispose 82f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall // CHECK: call void @_ZN5test21AD1Ev( 83f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall 84f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall // CHECK: define internal void @__Block_byref_object_copy 85f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall // CHECK: call void @_ZN5test21BC1ERKS0_( 86f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall 87f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall // CHECK: define internal void @__Block_byref_object_dispose 88f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall // CHECK: call void @_ZN5test21BD1Ev( 89f0c11f7e6848f023ced6a5b51399ba787c7d4d0bJohn McCall} 90642a75f883e644bcfbb82e7af0313776ad1ce33cJohn McCall 91642a75f883e644bcfbb82e7af0313776ad1ce33cJohn McCall// rdar://problem/9334739 92642a75f883e644bcfbb82e7af0313776ad1ce33cJohn McCall// Make sure we mark destructors for parameters captured in blocks. 93642a75f883e644bcfbb82e7af0313776ad1ce33cJohn McCallnamespace test3 { 94642a75f883e644bcfbb82e7af0313776ad1ce33cJohn McCall struct A { 95642a75f883e644bcfbb82e7af0313776ad1ce33cJohn McCall A(const A&); 96642a75f883e644bcfbb82e7af0313776ad1ce33cJohn McCall ~A(); 97642a75f883e644bcfbb82e7af0313776ad1ce33cJohn McCall }; 98642a75f883e644bcfbb82e7af0313776ad1ce33cJohn McCall 99642a75f883e644bcfbb82e7af0313776ad1ce33cJohn McCall struct B : A { 100642a75f883e644bcfbb82e7af0313776ad1ce33cJohn McCall }; 101642a75f883e644bcfbb82e7af0313776ad1ce33cJohn McCall 102642a75f883e644bcfbb82e7af0313776ad1ce33cJohn McCall void test(B b) { 103642a75f883e644bcfbb82e7af0313776ad1ce33cJohn McCall extern void consume(void(^)()); 104642a75f883e644bcfbb82e7af0313776ad1ce33cJohn McCall consume(^{ (void) b; }); 105642a75f883e644bcfbb82e7af0313776ad1ce33cJohn McCall } 106642a75f883e644bcfbb82e7af0313776ad1ce33cJohn McCall} 107d963c37eb912342c8325048749e449861cf0a6e3John McCall 108d963c37eb912342c8325048749e449861cf0a6e3John McCall// rdar://problem/9971485 109d963c37eb912342c8325048749e449861cf0a6e3John McCallnamespace test4 { 110d963c37eb912342c8325048749e449861cf0a6e3John McCall struct A { 111d963c37eb912342c8325048749e449861cf0a6e3John McCall A(); 112d963c37eb912342c8325048749e449861cf0a6e3John McCall ~A(); 113d963c37eb912342c8325048749e449861cf0a6e3John McCall }; 114d963c37eb912342c8325048749e449861cf0a6e3John McCall 115d963c37eb912342c8325048749e449861cf0a6e3John McCall void foo(A a); 116d963c37eb912342c8325048749e449861cf0a6e3John McCall 117d963c37eb912342c8325048749e449861cf0a6e3John McCall void test() { 118d963c37eb912342c8325048749e449861cf0a6e3John McCall extern void consume(void(^)()); 119d963c37eb912342c8325048749e449861cf0a6e3John McCall consume(^{ return foo(A()); }); 120d963c37eb912342c8325048749e449861cf0a6e3John McCall } 121d963c37eb912342c8325048749e449861cf0a6e3John McCall // CHECK: define void @_ZN5test44testEv() 122d963c37eb912342c8325048749e449861cf0a6e3John McCall // CHECK: define internal void @__test_block_invoke 123d963c37eb912342c8325048749e449861cf0a6e3John McCall // CHECK: [[TMP:%.*]] = alloca [[A:%.*]], align 1 124d963c37eb912342c8325048749e449861cf0a6e3John McCall // CHECK-NEXT: bitcast i8* 125d963c37eb912342c8325048749e449861cf0a6e3John McCall // CHECK-NEXT: call void @_ZN5test41AC1Ev([[A]]* [[TMP]]) 126d963c37eb912342c8325048749e449861cf0a6e3John McCall // CHECK-NEXT: call void @_ZN5test43fooENS_1AE([[A]]* [[TMP]]) 127d963c37eb912342c8325048749e449861cf0a6e3John McCall // CHECK-NEXT: call void @_ZN5test41AD1Ev([[A]]* [[TMP]]) 128d963c37eb912342c8325048749e449861cf0a6e3John McCall // CHECK-NEXT: ret void 129d963c37eb912342c8325048749e449861cf0a6e3John McCall} 130d963c37eb912342c8325048749e449861cf0a6e3John McCall 131b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCallnamespace test5 { 132b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall struct A { 133b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall unsigned afield; 134b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall A(); 135b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall A(const A&); 136b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall ~A(); 137b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall void foo() const; 138b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall }; 139b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall 140b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall void doWithBlock(void(^)()); 141b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall 142b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall void test(bool cond) { 143b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall A x; 144b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall void (^b)() = (cond ? ^{ x.foo(); } : (void(^)()) 0); 145b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall doWithBlock(b); 146b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall } 147b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall 148b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall // CHECK: define void @_ZN5test54testEb( 149b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall // CHECK: [[COND:%.*]] = alloca i8 150b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall // CHECK-NEXT: [[X:%.*]] = alloca [[A:%.*]], align 4 151b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall // CHECK-NEXT: [[B:%.*]] = alloca void ()*, align 8 152b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:.*]], align 8 153b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall // CHECK-NEXT: [[CLEANUP_ACTIVE:%.*]] = alloca i1 154b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall // CHECK-NEXT: store i1 false, i1* [[CLEANUP_ACTIVE]] 155b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall // CHECK-NEXT: [[T0:%.*]] = zext i1 156b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall // CHECK-NEXT: store i8 [[T0]], i8* [[COND]], align 1 157b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall // CHECK-NEXT: call void @_ZN5test51AC1Ev([[A]]* [[X]]) 158b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall // CHECK-NEXT: [[CLEANUP_ADDR:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 159b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall // CHECK-NEXT: [[T0:%.*]] = load i8* [[COND]], align 1 160b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall // CHECK-NEXT: [[T1:%.*]] = trunc i8 [[T0]] to i1 161b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall // CHECK-NEXT: br i1 [[T1]], 162b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall 163b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall // CHECK-NOT: br 164b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall // CHECK: [[CAPTURE:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 165b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall // CHECK-NEXT: call void @_ZN5test51AC1ERKS0_([[A]]* [[CAPTURE]], [[A]]* [[X]]) 166b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall // CHECK-NEXT: store i1 true, i1* [[CLEANUP_ACTIVE]] 167b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall // CHECK-NEXT: bitcast [[BLOCK_T]]* [[BLOCK]] to void ()* 168b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall // CHECK-NEXT: br label 169b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall // CHECK: br label 170b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall // CHECK: phi 171b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall // CHECK-NEXT: store 172b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall // CHECK-NEXT: load 173b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall // CHECK-NEXT: call void @_ZN5test511doWithBlockEU13block_pointerFvvE( 174b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall // CHECK-NEXT: [[T0:%.*]] = load i1* [[CLEANUP_ACTIVE]] 175b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall // CHECK-NEXT: br i1 [[T0]] 176b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall // CHECK: call void @_ZN5test51AD1Ev([[A]]* [[CLEANUP_ADDR]]) 177b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall // CHECK-NEXT: br label 178b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall // CHECK: call void @_ZN5test51AD1Ev([[A]]* [[X]]) 179b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall // CHECK-NEXT: ret void 180b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall} 181