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