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