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: define void @_ZN5test04testEi(
      5   // CHECK: define internal void @__test_block_invoke_{{.*}}(
      6   // CHECK: define internal void @__block_global_{{.*}}(
      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: 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: 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: 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: 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: define void @_ZN5test24testEv()
     73   void test() {
     74     __block A a;
     75     __block B b;
     76   }
     77 
     78   // CHECK: define internal void @__Block_byref_object_copy
     79   // CHECK: call void @_ZN5test21AC1ERKS0_(
     80 
     81   // CHECK: define internal void @__Block_byref_object_dispose
     82   // CHECK: call void @_ZN5test21AD1Ev(
     83 
     84   // CHECK: define internal void @__Block_byref_object_copy
     85   // CHECK: call void @_ZN5test21BC1ERKS0_(
     86 
     87   // CHECK: 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