blob: f9c4ff1b12356c816157bcd0713c78b811ae3004 [file] [log] [blame]
John McCall460ce582015-10-22 18:38:17 +00001// 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 @test1
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 @test2
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 @test3
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 @test4
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 @test5
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 @test6
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 id get_object(void);
105extern 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 @test7
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 @test8
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