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
33void 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
40void 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
52void 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
66void 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
78void 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
90void 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
104extern "C" id get_object(void);
105extern "C" void use_block(void (^)(void));
106
107void 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
128void 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
147void 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()
156void test9(void) {
157  __unsafe_unretained Foo *p = get_object();
158  use_block(^{ [p run]; });
159}
160void 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()
166void test10(void) {
167  typedef __unsafe_unretained Foo *UnsafeFooPtr;
168  UnsafeFooPtr p = get_object();
169  use_block(^{ [p run]; });
170}
171void 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()
177template <unsigned i> void test11(void) {
178  typedef __unsafe_unretained Foo *UnsafeFooPtr;
179  UnsafeFooPtr p = get_object();
180  use_block(^{ [p run]; });
181}
182template void test11<0>();
183void test11_fin() {}
184