Home | History | Annotate | Download | only in CodeGenObjCXX
      1 // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-runtime=macosx-10.10 -emit-llvm -fblocks -fobjc-weak -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-MODERN
      2 // RUN: %clang_cc1 -triple i386-apple-darwin10 -fobjc-runtime=macosx-fragile-10.10 -emit-llvm -fblocks -fobjc-weak -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-FRAGILE
      3 
      4 @interface Object
      5 - (instancetype) retain;
      6 - (void) run;
      7 @end
      8 
      9 // CHECK-MODERN: @OBJC_CLASS_NAME_{{.*}} = {{.*}} c"\01\00"
     10 // CHECK-MODERN: @"\01l_OBJC_CLASS_RO_$_Foo" = {{.*}} { i32 772
     11 //   772 == 0x304
     12 //            ^ HasMRCWeakIvars
     13 //            ^ HasCXXDestructorOnly
     14 //              ^ HasCXXStructors
     15 
     16 // CHECK-FRAGILE: @OBJC_CLASS_NAME_{{.*}} = {{.*}} c"\01\00"
     17 // CHECK-FRAGILE: @OBJC_CLASS_Foo = {{.*}} i32 134225921,
     18 //   134225921 == 0x08002001
     19 //                   ^ HasMRCWeakIvars
     20 //                      ^ HasCXXStructors
     21 //                         ^ Factory
     22 @interface Foo : Object {
     23   __weak id ivar;
     24 }
     25 @end
     26 
     27 @implementation Foo
     28 // CHECK-LABEL: define internal void @"\01-[Foo .cxx_destruct]"
     29 // CHECK: call void @objc_destroyWeak
     30 @end
     31 
     32 
     33 void test1(__weak id x) {}
     34 // CHECK-LABEL: define void @_Z5test1P11objc_object(
     35 // CHECK:      [[X:%.*]] = alloca i8*,
     36 // CHECK-NEXT: objc_initWeak
     37 // CHECK-NEXT: objc_destroyWeak
     38 // CHECK-NEXT: ret void
     39 
     40 void test2(id y) {
     41   __weak id z = y;
     42 }
     43 // CHECK-LABEL: define void @_Z5test2P11objc_object(
     44 // CHECK:      [[Y:%.*]] = alloca i8*,
     45 // CHECK-NEXT: [[Z:%.*]] = alloca i8*,
     46 // CHECK-NEXT: store
     47 // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[Y]]
     48 // CHECK-NEXT: call i8* @objc_initWeak(i8** [[Z]], i8* [[T0]])
     49 // CHECK-NEXT: call void @objc_destroyWeak(i8** [[Z]])
     50 // CHECK-NEXT: ret void
     51 
     52 void test3(id y) {
     53   __weak id z;
     54   z = y;
     55 }
     56 // CHECK-LABEL: define void @_Z5test3P11objc_object(
     57 // CHECK:      [[Y:%.*]] = alloca i8*,
     58 // CHECK-NEXT: [[Z:%.*]] = alloca i8*,
     59 // CHECK-NEXT: store
     60 // CHECK-NEXT: store i8* null, i8** [[Z]]
     61 // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[Y]]
     62 // CHECK-NEXT: call i8* @objc_storeWeak(i8** [[Z]], i8* [[T0]])
     63 // CHECK-NEXT: call void @objc_destroyWeak(i8** [[Z]])
     64 // CHECK-NEXT: ret void
     65 
     66 void test4(__weak id *p) {
     67   id y = *p;
     68 }
     69 // CHECK-LABEL: define void @_Z5test4PU6__weakP11objc_object(
     70 // CHECK:      [[P:%.*]] = alloca i8**,
     71 // CHECK-NEXT: [[Y:%.*]] = alloca i8*,
     72 // CHECK-NEXT: store
     73 // CHECK-NEXT: [[T0:%.*]] = load i8**, i8*** [[P]]
     74 // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_loadWeak(i8** [[T0]])
     75 // CHECK-NEXT: store i8* [[T1]], i8** [[Y]]
     76 // CHECK-NEXT: ret void
     77 
     78 void test5(__weak id *p) {
     79   id y = [*p retain];
     80 }
     81 // CHECK-LABEL: define void @_Z5test5PU6__weakP11objc_object
     82 // CHECK:      [[P:%.*]] = alloca i8**,
     83 // CHECK-NEXT: [[Y:%.*]] = alloca i8*,
     84 // CHECK-NEXT: store
     85 // CHECK-NEXT: [[T0:%.*]] = load i8**, i8*** [[P]]
     86 // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_loadWeakRetained(i8** [[T0]])
     87 // CHECK-NEXT: store i8* [[T1]], i8** [[Y]]
     88 // CHECK-NEXT: ret void
     89 
     90 void test6(__weak Foo **p) {
     91   Foo *y = [*p retain];
     92 }
     93 // CHECK-LABEL: define void @_Z5test6PU6__weakP3Foo
     94 // CHECK:      [[P:%.*]] = alloca [[FOO:%.*]]**,
     95 // CHECK-NEXT: [[Y:%.*]] = alloca [[FOO]]*,
     96 // CHECK-NEXT: store
     97 // CHECK-NEXT: [[T0:%.*]] = load [[FOO]]**, [[FOO]]*** [[P]]
     98 // CHECK-NEXT: [[T1:%.*]] = bitcast [[FOO]]** [[T0]] to i8**
     99 // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_loadWeakRetained(i8** [[T1]])
    100 // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[FOO]]*
    101 // CHECK-NEXT: store [[FOO]]* [[T3]], [[FOO]]** [[Y]]
    102 // CHECK-NEXT: ret void
    103 
    104 extern "C" id get_object(void);
    105 extern "C" void use_block(void (^)(void));
    106 
    107 void test7(void) {
    108   __weak Foo *p = get_object();
    109   use_block(^{ [p run ]; });
    110 }
    111 // CHECK-LABEL: define void @_Z5test7v
    112 // CHECK:       [[P:%.*]] = alloca [[FOO]]*,
    113 // CHECK:       [[T0:%.*]] = call i8* @get_object()
    114 // CHECK-NEXT:  [[T1:%.*]] = bitcast i8* [[T0]] to [[FOO]]*
    115 // CHECK-NEXT:  [[T2:%.*]] = bitcast [[FOO]]** [[P]] to i8**
    116 // CHECK-NEXT:  [[T3:%.*]] = bitcast [[FOO]]* [[T1]] to i8*
    117 // CHECK-NEXT:  call i8* @objc_initWeak(i8** [[T2]], i8* [[T3]])
    118 // CHECK:       call void @objc_copyWeak
    119 // CHECK:       call void @use_block
    120 // CHECK:       call void @objc_destroyWeak
    121 
    122 // CHECK-LABEL: define internal void @__copy_helper_block
    123 // CHECK:       @objc_copyWeak
    124 
    125 // CHECK-LABEL: define internal void @__destroy_helper_block
    126 // CHECK:       @objc_destroyWeak
    127 
    128 void test8(void) {
    129   __block __weak Foo *p = get_object();
    130   use_block(^{ [p run ]; });
    131 }
    132 // CHECK-LABEL: define void @_Z5test8v
    133 // CHECK:       call i8* @objc_initWeak
    134 // CHECK-NOT:   call void @objc_copyWeak
    135 // CHECK:       call void @use_block
    136 // CHECK:       call void @objc_destroyWeak
    137 
    138 // CHECK-LABEL: define internal void @__Block_byref_object_copy
    139 // CHECK:       call void @objc_moveWeak
    140 
    141 // CHECK-LABEL: define internal void @__Block_byref_object_dispose
    142 // CHECK:       call void @objc_destroyWeak
    143 
    144 // CHECK-LABEL: define void @_Z14test9_baselinev()
    145 // CHECK:       define internal void @__copy_helper
    146 // CHECK:       define internal void @__destroy_helper
    147 void test9_baseline(void) {
    148   Foo *p = get_object();
    149   use_block(^{ [p run]; });
    150 }
    151 
    152 // CHECK-LABEL: define void @_Z5test9v()
    153 // CHECK-NOT:   define internal void @__copy_helper
    154 // CHECK-NOT:   define internal void @__destroy_helper
    155 // CHECK:       define void @_Z9test9_finv()
    156 void test9(void) {
    157   __unsafe_unretained Foo *p = get_object();
    158   use_block(^{ [p run]; });
    159 }
    160 void test9_fin() {}
    161 
    162 // CHECK-LABEL: define void @_Z6test10v()
    163 // CHECK-NOT:   define internal void @__copy_helper
    164 // CHECK-NOT:   define internal void @__destroy_helper
    165 // CHECK:       define void @_Z10test10_finv()
    166 void test10(void) {
    167   typedef __unsafe_unretained Foo *UnsafeFooPtr;
    168   UnsafeFooPtr p = get_object();
    169   use_block(^{ [p run]; });
    170 }
    171 void test10_fin() {}
    172 
    173 // CHECK-LABEL: define weak_odr void @_Z6test11ILj0EEvv()
    174 // CHECK-NOT:   define internal void @__copy_helper
    175 // CHECK-NOT:   define internal void @__destroy_helper
    176 // CHECK:       define void @_Z10test11_finv()
    177 template <unsigned i> void test11(void) {
    178   typedef __unsafe_unretained Foo *UnsafeFooPtr;
    179   UnsafeFooPtr p = get_object();
    180   use_block(^{ [p run]; });
    181 }
    182 template void test11<0>();
    183 void test11_fin() {}
    184