Clang Project

clang_source_code/test/CodeGenObjCXX/arc-special-member-functions.mm
1// RUN: %clang_cc1 -std=c++11 -fobjc-arc -fblocks -triple x86_64-apple-darwin10.0.0 -fobjc-runtime-has-weak -emit-llvm -o - %s | FileCheck %s
2
3struct ObjCMember {
4  id member;
5};
6
7struct ObjCArrayMember {
8  id member[2][3];
9};
10
11struct ObjCBlockMember {
12  int (^bp)(int);
13};
14
15// CHECK: %[[STRUCT_CONTAINSWEAK:.*]] = type { %[[STRUCT_WEAK:.*]] }
16// CHECK: %[[STRUCT_WEAK]] = type { i8* }
17
18// The Weak object that is passed is destructed in this constructor.
19
20// CHECK: define void @_ZN12ContainsWeakC2E4Weak(
21// CHECK: call void @_ZN4WeakC1ERKS_(
22// CHECK: call void @_ZN4WeakD1Ev(
23
24// Check that the Weak object passed to this constructor is not destructed after
25// the delegate constructor is called.
26
27// CHECK: define void @_ZN12ContainsWeakC1E4Weak(
28// CHECK: call void @_ZN12ContainsWeakC2E4Weak(
29// CHECK-NEXT: ret void
30
31struct Weak {
32  Weak(id);
33  __weak id x;
34};
35
36struct ContainsWeak {
37  ContainsWeak(Weak);
38  Weak w;
39};
40
41ContainsWeak::ContainsWeak(Weak a) : w(a) {}
42
43// The Weak object that is passed is destructed in this constructor.
44
45// CHECK: define void @_ZN4BaseC2E4Weak(
46// CHECK: call void @_ZN4WeakD1Ev(
47// CHECK: ret void
48
49// Check that the Weak object passed to this constructor is not destructed after
50// the delegate constructor is called.
51
52// CHECK: define linkonce_odr void @_ZN7DerivedCI14BaseE4Weak(
53// CHECK: call void @_ZN7DerivedCI24BaseE4Weak(
54// CHECK-NEXT: ret void
55
56struct Base {
57  Base(Weak);
58};
59
60Base::Base(Weak a) {}
61
62struct Derived : Base {
63  using Base::Base;
64};
65
66Derived d(Weak(0));
67
68// CHECK-LABEL: define void @_Z42test_ObjCMember_default_construct_destructv(
69void test_ObjCMember_default_construct_destruct() {
70  // CHECK: call void @_ZN10ObjCMemberC1Ev
71  // CHECK: call void @_ZN10ObjCMemberD1Ev
72  ObjCMember m1;
73}
74
75// CHECK-LABEL: define void @_Z39test_ObjCMember_copy_construct_destruct10ObjCMember
76void test_ObjCMember_copy_construct_destruct(ObjCMember m1) {
77  // CHECK: call void @_ZN10ObjCMemberC1ERKS_
78  // CHECK: call void @_ZN10ObjCMemberD1Ev
79  ObjCMember m2 = m1;
80  // CHECK: ret void
81}
82
83// CHECK-LABEL: define void @_Z27test_ObjCMember_copy_assign10ObjCMemberS_
84void test_ObjCMember_copy_assign(ObjCMember m1, ObjCMember m2) {
85  // CHECK: {{call.*_ZN10ObjCMemberaSERKS_}}
86  m1 = m2;
87  // CHECK-NEXT: call void @_ZN10ObjCMemberD1Ev(
88  // CHECK-NEXT: call void @_ZN10ObjCMemberD1Ev(
89  // CHECK-NEXT: ret void
90}
91
92// Implicitly-generated copy assignment operator for ObjCMember
93// CHECK:    {{define linkonce_odr.*@_ZN10ObjCMemberaSERKS_}}
94// CHECK:      call void @llvm.objc.storeStrong
95// CHECK:      ret
96
97// CHECK-LABEL: define void @_Z47test_ObjCArrayMember_default_construct_destructv
98void test_ObjCArrayMember_default_construct_destruct() {
99  // CHECK: call void @_ZN15ObjCArrayMemberC1Ev
100  ObjCArrayMember m1;
101  // CHECK: call void @_ZN15ObjCArrayMemberD1Ev
102  // CHECK: ret void
103}
104
105// CHECK-LABEL: define void @_Z44test_ObjCArrayMember_copy_construct_destruct15ObjCArrayMember
106void test_ObjCArrayMember_copy_construct_destruct(ObjCArrayMember m1) {
107  // CHECK: call void @_ZN15ObjCArrayMemberC1ERKS_
108  ObjCArrayMember m2 = m1;
109  // CHECK: call void @_ZN15ObjCArrayMemberD1Ev
110  // CHECK: ret void
111}
112
113void test_ObjCArrayMember_copy_assign(ObjCArrayMember m1, ObjCArrayMember m2) {
114  // CHECK: {{call.*@_ZN15ObjCArrayMemberaSERKS_}}
115  m1 = m2;
116  // CHECK-NEXT: call void @_ZN15ObjCArrayMemberD1Ev(
117  // CHECK-NEXT: call void @_ZN15ObjCArrayMemberD1Ev(
118  // CHECK-NEXT: ret void
119}
120
121// Implicitly-generated copy assignment operator for ObjCArrayMember
122// CHECK: {{define linkonce_odr.*@_ZN15ObjCArrayMemberaSERKS_}}
123// CHECK:      call void @llvm.objc.storeStrong
124// CHECK-NEXT: br label
125// CHECK: ret
126
127// CHECK-LABEL: define void @_Z47test_ObjCBlockMember_default_construct_destructv
128void test_ObjCBlockMember_default_construct_destruct() {
129  // CHECK: call void @_ZN15ObjCBlockMemberC1Ev
130  ObjCBlockMember m;
131  // CHECK-NEXT: call void @_ZN15ObjCBlockMemberD1Ev
132  // CHECK-NEXT: ret void
133}
134
135// CHECK-LABEL: define void @_Z44test_ObjCBlockMember_copy_construct_destruct15ObjCBlockMember
136void test_ObjCBlockMember_copy_construct_destruct(ObjCBlockMember m1) {
137  // CHECK: call void @_ZN15ObjCBlockMemberC1ERKS_
138  ObjCBlockMember m2 = m1;
139  // CHECK-NEXT: call void @_ZN15ObjCBlockMemberD1Ev(
140  // CHECK-NEXT: call void @_ZN15ObjCBlockMemberD1Ev(
141  // CHECK-NEXT: ret void
142}
143
144// CHECK-LABEL: define void @_Z32test_ObjCBlockMember_copy_assign15ObjCBlockMemberS_
145void test_ObjCBlockMember_copy_assign(ObjCBlockMember m1, ObjCBlockMember m2) {
146  // CHECK: {{call.*_ZN15ObjCBlockMemberaSERKS_}}
147  m1 = m2;
148  // CHECK-NEXT: call void @_ZN15ObjCBlockMemberD1Ev(
149  // CHECK-NEXT: call void @_ZN15ObjCBlockMemberD1Ev(
150  // CHECK-NEXT: ret void
151}
152
153// Implicitly-generated copy assignment operator for ObjCBlockMember
154// CHECK:    define linkonce_odr dereferenceable({{[0-9]+}}) {{%.*}}* @_ZN15ObjCBlockMemberaSERKS_(
155// CHECK:      [[T0:%.*]] = getelementptr inbounds [[T:%.*]], [[T:%.*]]* {{%.*}}, i32 0, i32 0
156// CHECK-NEXT: [[T1:%.*]] = load i32 (i32)*, i32 (i32)** [[T0]], align 8
157// CHECK-NEXT: [[T2:%.*]] = bitcast i32 (i32)* [[T1]] to i8*
158// CHECK-NEXT: [[T3:%.*]] = call i8* @llvm.objc.retainBlock(i8* [[T2]])
159// CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to i32 (i32)*
160// CHECK-NEXT: [[T5:%.*]] = getelementptr inbounds [[T]], [[T]]* {{%.*}}, i32 0, i32 0
161// CHECK-NEXT: [[T6:%.*]] = load i32 (i32)*, i32 (i32)** [[T5]], align 8
162// CHECK-NEXT: store i32 (i32)* [[T4]], i32 (i32)** [[T5]]
163// CHECK-NEXT: [[T7:%.*]] = bitcast i32 (i32)* [[T6]] to i8*
164// CHECK-NEXT: call void @llvm.objc.release(i8* [[T7]])
165// CHECK-NEXT: ret
166
167// Check that the Weak object passed to this constructor is not destructed after
168// the delegate constructor is called.
169
170// CHECK: define linkonce_odr void @_ZN7DerivedCI24BaseE4Weak(
171// CHECK: call void @_ZN4BaseC2E4Weak(
172// CHECK-NEXT: ret void
173
174// Implicitly-generated default constructor for ObjCMember
175// CHECK-LABEL: define linkonce_odr void @_ZN10ObjCMemberC2Ev
176// CHECK-NOT: objc_release
177// CHECK: store i8* null
178// CHECK-NEXT: ret void
179
180// Implicitly-generated destructor for ObjCMember
181// CHECK-LABEL: define linkonce_odr void @_ZN10ObjCMemberD2Ev
182// CHECK: call void @llvm.objc.storeStrong
183// CHECK: ret void
184
185// Implicitly-generated copy constructor for ObjCMember
186// CHECK-LABEL: define linkonce_odr void @_ZN10ObjCMemberC2ERKS_
187// CHECK-NOT: objc_release
188// CHECK: call i8* @llvm.objc.retain
189// CHECK-NEXT: store i8*
190// CHECK-NEXT: ret void
191
192// Implicitly-generated default constructor for ObjCArrayMember
193// CHECK-LABEL: define linkonce_odr void @_ZN15ObjCArrayMemberC2Ev
194// CHECK: call void @llvm.memset.p0i8.i64
195// CHECK: ret
196
197// Implicitly-generated destructor for ObjCArrayMember
198// CHECK-LABEL:    define linkonce_odr void @_ZN15ObjCArrayMemberD2Ev
199// CHECK:      [[BEGIN:%.*]] = getelementptr inbounds [2 x [3 x i8*]], [2 x [3 x i8*]]*
200// CHECK-NEXT: [[END:%.*]] = getelementptr inbounds i8*, i8** [[BEGIN]], i64 6
201// CHECK-NEXT: br label
202// CHECK:      [[PAST:%.*]] = phi i8** [ [[END]], {{%.*}} ], [ [[CUR:%.*]], {{%.*}} ]
203// CHECK-NEXT: [[CUR]] = getelementptr inbounds i8*, i8** [[PAST]], i64 -1
204// CHECK-NEXT: call void @llvm.objc.storeStrong(i8** [[CUR]], i8* null)
205// CHECK-NEXT: [[T1:%.*]] = icmp eq i8** [[CUR]], [[BEGIN]]
206// CHECK-NEXT: br i1 [[T1]],
207// CHECK:      ret void
208
209// Implicitly-generated copy constructor for ObjCArrayMember
210// CHECK-LABEL: define linkonce_odr void @_ZN15ObjCArrayMemberC2ERKS_
211// CHECK: call i8* @llvm.objc.retain
212// CHECK-NEXT: store i8*
213// CHECK: br i1
214// CHECK: ret
215
216// Implicitly-generated default constructor for ObjCBlockMember
217// CHECK-LABEL: define linkonce_odr void @_ZN15ObjCBlockMemberC2Ev
218// CHECK: store {{.*}} null,
219// CHECK-NEXT: ret void
220
221// Implicitly-generated destructor for ObjCBlockMember
222// CHECK-LABEL: define linkonce_odr void @_ZN15ObjCBlockMemberD2Ev
223// CHECK: call void @llvm.objc.storeStrong(i8*
224// CHECK: ret
225
226// Implicitly-generated copy constructor for ObjCBlockMember
227// CHECK-LABEL: define linkonce_odr void @_ZN15ObjCBlockMemberC2ERKS_
228// CHECK: call i8* @llvm.objc.retainBlock
229// CHECK: ret
230
231