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