Home | History | Annotate | Download | only in CodeGenObjC
      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 // The ivars in HighlyAlignedSubclass should be placed in the tail-padding
     10 // of the superclass.  Ensure that they're still covered by layouts.
     11 @interface HighlyAligned : Object {
     12   __attribute__((aligned(32))) void *array[2];
     13 }
     14 @end
     15 // CHECK-MODERN: @"OBJC_IVAR_$_HighlyAlignedSubclass.ivar2" = global i64 24,
     16 // CHECK-MODERN: @"OBJC_IVAR_$_HighlyAlignedSubclass.ivar" = global i64 16,
     17 // CHECK-MODERN: @OBJC_CLASS_NAME_{{.*}} = {{.*}} c"\02\00"
     18 // CHECK-MODERN: @"\01l_OBJC_CLASS_RO_$_HighlyAlignedSubclass" = {{.*}} {
     19 // CHECK-FRAGILE: @OBJC_INSTANCE_VARIABLES_HighlyAlignedSubclass = {{.*}}, i32 8 }, {{.*}}, i32 12 }]
     20 // CHECK-FRAGILE: @OBJC_CLASS_NAME_{{.*}} = {{.*}} c"\02\00"
     21 // CHECK-FRAGILE: @OBJC_CLASS_HighlyAlignedSubclass
     22 @interface HighlyAlignedSubclass : HighlyAligned {
     23   __weak id ivar;
     24   __weak id ivar2;
     25 }
     26 @end
     27 @implementation HighlyAlignedSubclass @end
     28 
     29 // CHECK-MODERN: @OBJC_CLASS_NAME_{{.*}} = {{.*}} c"\01\00"
     30 // CHECK-MODERN: @"\01l_OBJC_CLASS_RO_$_Foo" = {{.*}} { i32 772
     31 //   772 == 0x304
     32 //            ^ HasMRCWeakIvars
     33 //            ^ HasCXXDestructorOnly
     34 //              ^ HasCXXStructors
     35 
     36 // CHECK-FRAGILE: @OBJC_CLASS_NAME_{{.*}} = {{.*}} c"\01\00"
     37 // CHECK-FRAGILE: @OBJC_CLASS_Foo = {{.*}} i32 134225921,
     38 //   134225921 == 0x08002001
     39 //                   ^ HasMRCWeakIvars
     40 //                      ^ HasCXXStructors
     41 //                         ^ Factory
     42 @interface Foo : Object {
     43   __weak id ivar;
     44 }
     45 @end
     46 
     47 @implementation Foo
     48 // CHECK-LABEL: define internal void @"\01-[Foo .cxx_destruct]"
     49 // CHECK: call void @objc_destroyWeak
     50 @end
     51 
     52 
     53 void test1(__weak id x) {}
     54 // CHECK-LABEL: define void @test1
     55 // CHECK:      [[X:%.*]] = alloca i8*,
     56 // CHECK-NEXT: objc_initWeak
     57 // CHECK-NEXT: objc_destroyWeak
     58 // CHECK-NEXT: ret void
     59 
     60 void test2(id y) {
     61   __weak id z = y;
     62 }
     63 // CHECK-LABEL: define void @test2
     64 // CHECK:      [[Y:%.*]] = alloca i8*,
     65 // CHECK-NEXT: [[Z:%.*]] = alloca i8*,
     66 // CHECK-NEXT: store
     67 // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[Y]]
     68 // CHECK-NEXT: call i8* @objc_initWeak(i8** [[Z]], i8* [[T0]])
     69 // CHECK-NEXT: call void @objc_destroyWeak(i8** [[Z]])
     70 // CHECK-NEXT: ret void
     71 
     72 void test3(id y) {
     73   __weak id z;
     74   z = y;
     75 }
     76 // CHECK-LABEL: define void @test3
     77 // CHECK:      [[Y:%.*]] = alloca i8*,
     78 // CHECK-NEXT: [[Z:%.*]] = alloca i8*,
     79 // CHECK-NEXT: store
     80 // CHECK-NEXT: store i8* null, i8** [[Z]]
     81 // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[Y]]
     82 // CHECK-NEXT: call i8* @objc_storeWeak(i8** [[Z]], i8* [[T0]])
     83 // CHECK-NEXT: call void @objc_destroyWeak(i8** [[Z]])
     84 // CHECK-NEXT: ret void
     85 
     86 void test4(__weak id *p) {
     87   id y = *p;
     88 }
     89 // CHECK-LABEL: define void @test4
     90 // CHECK:      [[P:%.*]] = alloca i8**,
     91 // CHECK-NEXT: [[Y:%.*]] = alloca i8*,
     92 // CHECK-NEXT: store
     93 // CHECK-NEXT: [[T0:%.*]] = load i8**, i8*** [[P]]
     94 // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_loadWeak(i8** [[T0]])
     95 // CHECK-NEXT: store i8* [[T1]], i8** [[Y]]
     96 // CHECK-NEXT: ret void
     97 
     98 void test5(__weak id *p) {
     99   id y = [*p retain];
    100 }
    101 // CHECK-LABEL: define void @test5
    102 // CHECK:      [[P:%.*]] = alloca i8**,
    103 // CHECK-NEXT: [[Y:%.*]] = alloca i8*,
    104 // CHECK-NEXT: store
    105 // CHECK-NEXT: [[T0:%.*]] = load i8**, i8*** [[P]]
    106 // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_loadWeakRetained(i8** [[T0]])
    107 // CHECK-NEXT: store i8* [[T1]], i8** [[Y]]
    108 // CHECK-NEXT: ret void
    109 
    110 void test6(__weak Foo **p) {
    111   Foo *y = [*p retain];
    112 }
    113 // CHECK-LABEL: define void @test6
    114 // CHECK:      [[P:%.*]] = alloca [[FOO:%.*]]**,
    115 // CHECK-NEXT: [[Y:%.*]] = alloca [[FOO]]*,
    116 // CHECK-NEXT: store
    117 // CHECK-NEXT: [[T0:%.*]] = load [[FOO]]**, [[FOO]]*** [[P]]
    118 // CHECK-NEXT: [[T1:%.*]] = bitcast [[FOO]]** [[T0]] to i8**
    119 // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_loadWeakRetained(i8** [[T1]])
    120 // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[FOO]]*
    121 // CHECK-NEXT: store [[FOO]]* [[T3]], [[FOO]]** [[Y]]
    122 // CHECK-NEXT: ret void
    123 
    124 extern id get_object(void);
    125 extern void use_block(void (^)(void));
    126 
    127 void test7(void) {
    128   __weak Foo *p = get_object();
    129   use_block(^{ [p run ]; });
    130 }
    131 // CHECK-LABEL: define void @test7
    132 // CHECK:       [[P:%.*]] = alloca [[FOO]]*,
    133 // CHECK:       [[T0:%.*]] = call i8* @get_object()
    134 // CHECK-NEXT:  [[T1:%.*]] = bitcast i8* [[T0]] to [[FOO]]*
    135 // CHECK-NEXT:  [[T2:%.*]] = bitcast [[FOO]]** [[P]] to i8**
    136 // CHECK-NEXT:  [[T3:%.*]] = bitcast [[FOO]]* [[T1]] to i8*
    137 // CHECK-NEXT:  call i8* @objc_initWeak(i8** [[T2]], i8* [[T3]])
    138 // CHECK:       call void @objc_copyWeak
    139 // CHECK:       call void @use_block
    140 // CHECK:       call void @objc_destroyWeak
    141 
    142 // CHECK-LABEL: define internal void @__copy_helper_block
    143 // CHECK:       @objc_copyWeak
    144 
    145 // CHECK-LABEL: define internal void @__destroy_helper_block
    146 // CHECK:       @objc_destroyWeak
    147 
    148 void test8(void) {
    149   __block __weak Foo *p = get_object();
    150   use_block(^{ [p run ]; });
    151 }
    152 // CHECK-LABEL: define void @test8
    153 // CHECK:       call i8* @objc_initWeak
    154 // CHECK-NOT:   call void @objc_copyWeak
    155 // CHECK:       call void @use_block
    156 // CHECK:       call void @objc_destroyWeak
    157 
    158 // CHECK-LABEL: define internal void @__Block_byref_object_copy
    159 // CHECK:       call void @objc_moveWeak
    160 
    161 // CHECK-LABEL: define internal void @__Block_byref_object_dispose
    162 // CHECK:       call void @objc_destroyWeak
    163 
    164 // CHECK-LABEL: define void @test9_baseline()
    165 // CHECK:       define internal void @__copy_helper
    166 // CHECK:       define internal void @__destroy_helper
    167 void test9_baseline(void) {
    168   Foo *p = get_object();
    169   use_block(^{ [p run]; });
    170 }
    171 
    172 // CHECK-LABEL: define void @test9()
    173 // CHECK-NOT:   define internal void @__copy_helper
    174 // CHECK-NOT:   define internal void @__destroy_helper
    175 // CHECK:       define void @test9_fin()
    176 void test9(void) {
    177   __unsafe_unretained Foo *p = get_object();
    178   use_block(^{ [p run]; });
    179 }
    180 void test9_fin() {}
    181 
    182 // CHECK-LABEL: define void @test10()
    183 // CHECK-NOT:   define internal void @__copy_helper
    184 // CHECK-NOT:   define internal void @__destroy_helper
    185 // CHECK:       define void @test10_fin()
    186 void test10(void) {
    187   typedef __unsafe_unretained Foo *UnsafeFooPtr;
    188   UnsafeFooPtr p = get_object();
    189   use_block(^{ [p run]; });
    190 }
    191 void test10_fin() {}
    192