xref: /llvm-project/clang/test/CodeGenObjCXX/mrc-weak.mm (revision 9466b49171dc4b21f56a48594fc82b1e52f5358a)
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: @"_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 @llvm.objc.destroyWeak
30@end
31
32
33void test1(__weak id x) {}
34// CHECK-LABEL: define{{.*}} void @_Z5test1P11objc_object(
35// CHECK:      [[X:%.*]] = alloca ptr,
36// CHECK-NEXT: llvm.objc.initWeak
37// CHECK-NEXT: llvm.objc.destroyWeak
38// CHECK-NEXT: ret void
39
40void test2(id y) {
41  __weak id z = y;
42}
43// CHECK-LABEL: define{{.*}} void @_Z5test2P11objc_object(
44// CHECK:      [[Y:%.*]] = alloca ptr,
45// CHECK-NEXT: [[Z:%.*]] = alloca ptr,
46// CHECK-NEXT: store
47// CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[Y]]
48// CHECK-NEXT: call ptr @llvm.objc.initWeak(ptr [[Z]], ptr [[T0]])
49// CHECK-NEXT: call void @llvm.objc.destroyWeak(ptr [[Z]])
50// CHECK-NEXT: ret void
51
52void test3(id y) {
53  __weak id z;
54  z = y;
55}
56// CHECK-LABEL: define{{.*}} void @_Z5test3P11objc_object(
57// CHECK:      [[Y:%.*]] = alloca ptr,
58// CHECK-NEXT: [[Z:%.*]] = alloca ptr,
59// CHECK-NEXT: store
60// CHECK-NEXT: store ptr null, ptr [[Z]]
61// CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[Y]]
62// CHECK-NEXT: call ptr @llvm.objc.storeWeak(ptr [[Z]], ptr [[T0]])
63// CHECK-NEXT: call void @llvm.objc.destroyWeak(ptr [[Z]])
64// CHECK-NEXT: ret void
65
66void test4(__weak id *p) {
67  id y = *p;
68}
69// CHECK-LABEL: define{{.*}} void @_Z5test4PU6__weakP11objc_object(
70// CHECK:      [[P:%.*]] = alloca ptr,
71// CHECK-NEXT: [[Y:%.*]] = alloca ptr,
72// CHECK-NEXT: store
73// CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[P]]
74// CHECK-NEXT: [[T1:%.*]] = call ptr @llvm.objc.loadWeak(ptr [[T0]])
75// CHECK-NEXT: store ptr [[T1]], ptr [[Y]]
76// CHECK-NEXT: ret void
77
78void test5(__weak id *p) {
79  id y = [*p retain];
80}
81// CHECK-LABEL: define{{.*}} void @_Z5test5PU6__weakP11objc_object
82// CHECK:      [[P:%.*]] = alloca ptr,
83// CHECK-NEXT: [[Y:%.*]] = alloca ptr,
84// CHECK-NEXT: store
85// CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[P]]
86// CHECK-NEXT: [[T1:%.*]] = call ptr @llvm.objc.loadWeakRetained(ptr [[T0]])
87// CHECK-NEXT: store ptr [[T1]], ptr [[Y]]
88// CHECK-NEXT: ret void
89
90void test6(__weak Foo **p) {
91  Foo *y = [*p retain];
92}
93// CHECK-LABEL: define{{.*}} void @_Z5test6PU6__weakP3Foo
94// CHECK:      [[P:%.*]] = alloca ptr,
95// CHECK-NEXT: [[Y:%.*]] = alloca ptr,
96// CHECK-NEXT: store
97// CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[P]]
98// CHECK-NEXT: [[T2:%.*]] = call ptr @llvm.objc.loadWeakRetained(ptr [[T0]])
99// CHECK-NEXT: store ptr [[T2]], ptr [[Y]]
100// CHECK-NEXT: ret void
101
102extern "C" id get_object(void);
103extern "C" void use_block(void (^)(void));
104
105void test7(void) {
106  __weak Foo *p = get_object();
107  use_block(^{ [p run ]; });
108}
109// CHECK-LABEL: define{{.*}} void @_Z5test7v
110// CHECK:       [[P:%.*]] = alloca ptr,
111// CHECK:       [[T0:%.*]] = call ptr @get_object()
112// CHECK-NEXT:  call ptr @llvm.objc.initWeak(ptr [[P]], ptr [[T0]])
113// CHECK:       call void @llvm.objc.copyWeak
114// CHECK:       call void @use_block
115// CHECK:       call void @llvm.objc.destroyWeak
116
117// CHECK-LABEL: define linkonce_odr hidden void @__copy_helper_block
118// CHECK:       @llvm.objc.copyWeak
119
120// CHECK-LABEL: define linkonce_odr hidden void @__destroy_helper_block
121// CHECK:       @llvm.objc.destroyWeak
122
123void test8(void) {
124  __block __weak Foo *p = get_object();
125  use_block(^{ [p run ]; });
126}
127// CHECK-LABEL: define{{.*}} void @_Z5test8v
128// CHECK:       call ptr @llvm.objc.initWeak
129// CHECK-NOT:   call void @llvm.objc.copyWeak
130// CHECK:       call void @use_block
131// CHECK:       call void @llvm.objc.destroyWeak
132
133// CHECK-LABEL: define internal void @__Block_byref_object_copy
134// CHECK:       call void @llvm.objc.moveWeak
135
136// CHECK-LABEL: define internal void @__Block_byref_object_dispose
137// CHECK:       call void @llvm.objc.destroyWeak
138
139// CHECK-LABEL: define{{.*}} void @_Z14test9_baselinev()
140// CHECK:       define linkonce_odr hidden void @__copy_helper
141// CHECK:       define linkonce_odr hidden void @__destroy_helper
142void test9_baseline(void) {
143  Foo *p = get_object();
144  use_block(^{ [p run]; });
145}
146
147// CHECK-LABEL: define{{.*}} void @_Z5test9v()
148// CHECK-NOT:   define internal void @__copy_helper
149// CHECK-NOT:   define internal void @__destroy_helper
150// CHECK:       define{{.*}} void @_Z9test9_finv()
151void test9(void) {
152  __unsafe_unretained Foo *p = get_object();
153  use_block(^{ [p run]; });
154}
155void test9_fin() {}
156
157// CHECK-LABEL: define{{.*}} void @_Z6test10v()
158// CHECK-NOT:   define internal void @__copy_helper
159// CHECK-NOT:   define internal void @__destroy_helper
160// CHECK:       define{{.*}} void @_Z10test10_finv()
161void test10(void) {
162  typedef __unsafe_unretained Foo *UnsafeFooPtr;
163  UnsafeFooPtr p = get_object();
164  use_block(^{ [p run]; });
165}
166void test10_fin() {}
167
168// CHECK-LABEL: define weak_odr void @_Z6test11ILj0EEvv()
169// CHECK-NOT:   define internal void @__copy_helper
170// CHECK-NOT:   define internal void @__destroy_helper
171// CHECK:       define{{.*}} void @_Z10test11_finv()
172template <unsigned i> void test11(void) {
173  typedef __unsafe_unretained Foo *UnsafeFooPtr;
174  UnsafeFooPtr p = get_object();
175  use_block(^{ [p run]; });
176}
177template void test11<0>();
178void test11_fin() {}
179