xref: /aosp_15_r20/external/clang/test/CodeGenObjCXX/arc.mm (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-runtime-has-weak -fblocks -fobjc-arc -O2 -disable-llvm-optzns -o - %s | FileCheck %s
2*67e74705SXin Li
3*67e74705SXin Listruct NSFastEnumerationState;
4*67e74705SXin Li@interface NSArray
5*67e74705SXin Li- (unsigned long) countByEnumeratingWithState: (struct NSFastEnumerationState*) state
6*67e74705SXin Li                  objects: (id*) buffer
7*67e74705SXin Li                  count: (unsigned long) bufferSize;
8*67e74705SXin Li@end;
9*67e74705SXin LiNSArray *nsarray() { return 0; }
10*67e74705SXin Li// CHECK: define [[NSARRAY:%.*]]* @_Z7nsarrayv()
11*67e74705SXin Li
12*67e74705SXin Livoid use(id);
13*67e74705SXin Li
14*67e74705SXin Li// rdar://problem/9315552
15*67e74705SXin Li// The analogous ObjC testcase test46 in arr.m.
16*67e74705SXin Livoid test0(__weak id *wp, __weak volatile id *wvp) {
17*67e74705SXin Li  extern id test0_helper(void);
18*67e74705SXin Li
19*67e74705SXin Li  // TODO: this is sub-optimal, we should retain at the actual call site.
20*67e74705SXin Li  // TODO: in the non-volatile case, we do not need to be reloading.
21*67e74705SXin Li
22*67e74705SXin Li  // CHECK:      [[T0:%.*]] = call i8* @_Z12test0_helperv()
23*67e74705SXin Li  // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
24*67e74705SXin Li  // CHECK-NEXT: [[T2:%.*]] = load i8**, i8*** {{%.*}}, align 8
25*67e74705SXin Li  // CHECK-NEXT: [[T3:%.*]] = call i8* @objc_storeWeak(i8** [[T2]], i8* [[T1]])
26*67e74705SXin Li  // CHECK-NEXT: [[T4:%.*]] = call i8* @objc_retain(i8* [[T3]])
27*67e74705SXin Li  // CHECK-NEXT: store i8* [[T4]], i8**
28*67e74705SXin Li  // CHECK-NEXT: call void @objc_release(i8* [[T1]])
29*67e74705SXin Li  id x = *wp = test0_helper();
30*67e74705SXin Li
31*67e74705SXin Li  // CHECK:      [[T0:%.*]] = call i8* @_Z12test0_helperv()
32*67e74705SXin Li  // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
33*67e74705SXin Li  // CHECK-NEXT: [[T2:%.*]] = load i8**, i8*** {{%.*}}, align 8
34*67e74705SXin Li  // CHECK-NEXT: [[T3:%.*]] = call i8* @objc_storeWeak(i8** [[T2]], i8* [[T1]])
35*67e74705SXin Li  // CHECK-NEXT: [[T4:%.*]] = call i8* @objc_loadWeakRetained(i8** [[T2]])
36*67e74705SXin Li  // CHECK-NEXT: store i8* [[T4]], i8**
37*67e74705SXin Li  // CHECK-NEXT: call void @objc_release(i8* [[T1]])
38*67e74705SXin Li  id y = *wvp = test0_helper();
39*67e74705SXin Li}
40*67e74705SXin Li
41*67e74705SXin Li// rdar://problem/9320648
42*67e74705SXin Listruct Test1_helper { Test1_helper(); };
43*67e74705SXin Li@interface Test1 @end
44*67e74705SXin Li@implementation Test1 { Test1_helper x; } @end
45*67e74705SXin Li// CHECK: define internal i8* @"\01-[Test1 .cxx_construct]"(
46*67e74705SXin Li// CHECK:      call void @_ZN12Test1_helperC1Ev(
47*67e74705SXin Li// CHECK-NEXT: load
48*67e74705SXin Li// CHECK-NEXT: bitcast
49*67e74705SXin Li// CHECK-NEXT: ret i8*
50*67e74705SXin Li
51*67e74705SXin Livoid test34(int cond) {
52*67e74705SXin Li  __strong id strong;
53*67e74705SXin Li  __weak id weak;
54*67e74705SXin Li  extern void test34_sink(id *);
55*67e74705SXin Li  test34_sink(cond ? &strong : 0);
56*67e74705SXin Li  test34_sink(cond ? &weak : 0);
57*67e74705SXin Li
58*67e74705SXin Li  // CHECK-LABEL:    define void @_Z6test34i(
59*67e74705SXin Li  // CHECK:      [[COND:%.*]] = alloca i32
60*67e74705SXin Li  // CHECK-NEXT: [[STRONG:%.*]] = alloca i8*
61*67e74705SXin Li  // CHECK-NEXT: [[WEAK:%.*]] = alloca i8*
62*67e74705SXin Li  // CHECK-NEXT: [[TEMP1:%.*]] = alloca i8*
63*67e74705SXin Li  // CHECK-NEXT: [[TEMP2:%.*]] = alloca i8*
64*67e74705SXin Li  // CHECK-NEXT: [[CONDCLEANUPSAVE:%.*]] = alloca i8*
65*67e74705SXin Li  // CHECK-NEXT: [[CONDCLEANUP:%.*]] = alloca i1
66*67e74705SXin Li  // CHECK-NEXT: store i32
67*67e74705SXin Li  // CHECK-NEXT: [[STRONGP:%.*]] = bitcast i8** [[STRONG]] to i8*
68*67e74705SXin Li  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[STRONGP]])
69*67e74705SXin Li  // CHECK-NEXT: store i8* null, i8** [[STRONG]]
70*67e74705SXin Li  // CHECK-NEXT: [[WEAKP:%.*]] = bitcast i8** [[WEAK]] to i8*
71*67e74705SXin Li  // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[WEAKP]])
72*67e74705SXin Li  // CHECK-NEXT: call i8* @objc_initWeak(i8** [[WEAK]], i8* null)
73*67e74705SXin Li
74*67e74705SXin Li  // CHECK-NEXT: [[T0:%.*]] = load i32, i32* [[COND]]
75*67e74705SXin Li  // CHECK-NEXT: [[T1:%.*]] = icmp ne i32 [[T0]], 0
76*67e74705SXin Li  // CHECK:      [[ARG:%.*]] = phi i8**
77*67e74705SXin Li  // CHECK-NEXT: [[T0:%.*]] = icmp eq i8** [[ARG]], null
78*67e74705SXin Li  // CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], i8** null, i8** [[TEMP1]]
79*67e74705SXin Li  // CHECK-NEXT: br i1 [[T0]],
80*67e74705SXin Li  // CHECK:      [[T0:%.*]] = load i8*, i8** [[ARG]]
81*67e74705SXin Li  // CHECK-NEXT: store i8* [[T0]], i8** [[TEMP1]]
82*67e74705SXin Li  // CHECK-NEXT: br label
83*67e74705SXin Li  // CHECK:      [[W0:%.*]] = phi i8* [ [[T0]], {{%.*}} ], [ undef, {{%.*}} ]
84*67e74705SXin Li  // CHECK:      call void @_Z11test34_sinkPU15__autoreleasingP11objc_object(i8** [[T1]])
85*67e74705SXin Li  // CHECK-NEXT: [[T0:%.*]] = icmp eq i8** [[ARG]], null
86*67e74705SXin Li  // CHECK-NEXT: br i1 [[T0]],
87*67e74705SXin Li  // CHECK:      [[T0:%.*]] = load i8*, i8** [[TEMP1]]
88*67e74705SXin Li  // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]])
89*67e74705SXin Li  // CHECK-NEXT: call void (...) @clang.arc.use(i8* [[W0]])
90*67e74705SXin Li  // CHECK-NEXT: [[T2:%.*]] = load i8*, i8** [[ARG]]
91*67e74705SXin Li  // CHECK-NEXT: store i8* [[T1]], i8** [[ARG]]
92*67e74705SXin Li  // CHECK-NEXT: call void @objc_release(i8* [[T2]])
93*67e74705SXin Li  // CHECK-NEXT: br label
94*67e74705SXin Li
95*67e74705SXin Li  // CHECK:      [[T0:%.*]] = load i32, i32* [[COND]]
96*67e74705SXin Li  // CHECK-NEXT: [[T1:%.*]] = icmp ne i32 [[T0]], 0
97*67e74705SXin Li  // CHECK:      [[ARG:%.*]] = phi i8**
98*67e74705SXin Li  // CHECK-NEXT: [[T0:%.*]] = icmp eq i8** [[ARG]], null
99*67e74705SXin Li  // CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], i8** null, i8** [[TEMP2]]
100*67e74705SXin Li  // CHECK-NEXT: store i1 false, i1* [[CONDCLEANUP]]
101*67e74705SXin Li  // CHECK-NEXT: br i1 [[T0]],
102*67e74705SXin Li  // CHECK:      [[T0:%.*]] = call i8* @objc_loadWeakRetained(i8** [[ARG]])
103*67e74705SXin Li  // CHECK-NEXT: store i8* [[T0]], i8** [[CONDCLEANUPSAVE]]
104*67e74705SXin Li  // CHECK-NEXT: store i1 true, i1* [[CONDCLEANUP]]
105*67e74705SXin Li  // CHECK-NEXT: store i8* [[T0]], i8** [[TEMP2]]
106*67e74705SXin Li  // CHECK-NEXT: br label
107*67e74705SXin Li  // CHECK:      call void @_Z11test34_sinkPU15__autoreleasingP11objc_object(i8** [[T1]])
108*67e74705SXin Li  // CHECK-NEXT: [[T0:%.*]] = icmp eq i8** [[ARG]], null
109*67e74705SXin Li  // CHECK-NEXT: br i1 [[T0]],
110*67e74705SXin Li  // CHECK:      [[T0:%.*]] = load i8*, i8** [[TEMP2]]
111*67e74705SXin Li  // CHECK-NEXT: call i8* @objc_storeWeak(i8** [[ARG]], i8* [[T0]])
112*67e74705SXin Li  // CHECK-NEXT: br label
113*67e74705SXin Li
114*67e74705SXin Li  // CHECK:      call void @objc_destroyWeak(i8** [[WEAK]])
115*67e74705SXin Li  // CHECK:      ret void
116*67e74705SXin Li}
117*67e74705SXin Li
118*67e74705SXin Listruct Test35_Helper {
119*67e74705SXin Li  static id makeObject1() __attribute__((ns_returns_retained));
120*67e74705SXin Li  id makeObject2() __attribute__((ns_returns_retained));
121*67e74705SXin Li  static id makeObject3();
122*67e74705SXin Li  id makeObject4();
123*67e74705SXin Li};
124*67e74705SXin Li
125*67e74705SXin Li// CHECK-LABEL: define void @_Z6test3513Test35_HelperPS_
126*67e74705SXin Livoid test35(Test35_Helper x0, Test35_Helper *x0p) {
127*67e74705SXin Li  // CHECK: call void @llvm.lifetime.start
128*67e74705SXin Li  // CHECK: call i8* @_ZN13Test35_Helper11makeObject1Ev
129*67e74705SXin Li  // CHECK-NOT: call i8* @objc_retain
130*67e74705SXin Li  id obj1 = Test35_Helper::makeObject1();
131*67e74705SXin Li  // CHECK: call void @llvm.lifetime.start
132*67e74705SXin Li  // CHECK: call i8* @_ZN13Test35_Helper11makeObject2Ev
133*67e74705SXin Li  // CHECK-NOT: call i8* @objc_retain
134*67e74705SXin Li  id obj2 = x0.makeObject2();
135*67e74705SXin Li  // CHECK: call void @llvm.lifetime.start
136*67e74705SXin Li  // CHECK: call i8* @_ZN13Test35_Helper11makeObject2Ev
137*67e74705SXin Li  // CHECK-NOT: call i8* @objc_retain
138*67e74705SXin Li  id obj3 = x0p->makeObject2();
139*67e74705SXin Li  id (Test35_Helper::*pmf)() __attribute__((ns_returns_retained))
140*67e74705SXin Li    = &Test35_Helper::makeObject2;
141*67e74705SXin Li  // CHECK: call void @llvm.lifetime.start
142*67e74705SXin Li  // CHECK: call i8* %
143*67e74705SXin Li  // CHECK-NOT: call i8* @objc_retain
144*67e74705SXin Li  id obj4 = (x0.*pmf)();
145*67e74705SXin Li  // CHECK: call void @llvm.lifetime.start
146*67e74705SXin Li  // CHECK: call i8* %
147*67e74705SXin Li  // CHECK-NOT: call i8* @objc_retain
148*67e74705SXin Li  id obj5 = (x0p->*pmf)();
149*67e74705SXin Li
150*67e74705SXin Li  // CHECK: call void @objc_release
151*67e74705SXin Li  // CHECK: call void @llvm.lifetime.end
152*67e74705SXin Li  // CHECK: call void @objc_release
153*67e74705SXin Li  // CHECK: call void @llvm.lifetime.end
154*67e74705SXin Li  // CHECK: call void @objc_release
155*67e74705SXin Li  // CHECK: call void @llvm.lifetime.end
156*67e74705SXin Li  // CHECK: call void @objc_release
157*67e74705SXin Li  // CHECK: call void @llvm.lifetime.end
158*67e74705SXin Li  // CHECK: call void @objc_release
159*67e74705SXin Li  // CHECK: call void @llvm.lifetime.end
160*67e74705SXin Li  // CHECK-NEXT: ret void
161*67e74705SXin Li}
162*67e74705SXin Li
163*67e74705SXin Li// CHECK-LABEL: define void @_Z7test35b13Test35_HelperPS_
164*67e74705SXin Livoid test35b(Test35_Helper x0, Test35_Helper *x0p) {
165*67e74705SXin Li  // CHECK: call void @llvm.lifetime.start
166*67e74705SXin Li  // CHECK: call i8* @_ZN13Test35_Helper11makeObject3Ev
167*67e74705SXin Li  // CHECK: call i8* @objc_retain
168*67e74705SXin Li  id obj1 = Test35_Helper::makeObject3();
169*67e74705SXin Li  // CHECK: call void @llvm.lifetime.start
170*67e74705SXin Li  // CHECK: call i8* @_ZN13Test35_Helper11makeObject4Ev
171*67e74705SXin Li  // CHECK: call i8* @objc_retain
172*67e74705SXin Li  id obj2 = x0.makeObject4();
173*67e74705SXin Li  // CHECK: call void @llvm.lifetime.start
174*67e74705SXin Li  // CHECK: call i8* @_ZN13Test35_Helper11makeObject4Ev
175*67e74705SXin Li  // CHECK: call i8* @objc_retain
176*67e74705SXin Li  id obj3 = x0p->makeObject4();
177*67e74705SXin Li  id (Test35_Helper::*pmf)() = &Test35_Helper::makeObject4;
178*67e74705SXin Li  // CHECK: call void @llvm.lifetime.start
179*67e74705SXin Li  // CHECK: call i8* %
180*67e74705SXin Li  // CHECK: call i8* @objc_retain
181*67e74705SXin Li  id obj4 = (x0.*pmf)();
182*67e74705SXin Li  // CHECK: call void @llvm.lifetime.start
183*67e74705SXin Li  // CHECK: call i8* %
184*67e74705SXin Li  // CHECK: call i8* @objc_retain
185*67e74705SXin Li  id obj5 = (x0p->*pmf)();
186*67e74705SXin Li
187*67e74705SXin Li  // CHECK: call void @objc_release
188*67e74705SXin Li  // CHECK: call void @llvm.lifetime.end
189*67e74705SXin Li  // CHECK: call void @objc_release
190*67e74705SXin Li  // CHECK: call void @llvm.lifetime.end
191*67e74705SXin Li  // CHECK: call void @llvm.lifetime.end
192*67e74705SXin Li  // CHECK: call void @objc_release
193*67e74705SXin Li  // CHECK: call void @llvm.lifetime.end
194*67e74705SXin Li  // CHECK: call void @objc_release
195*67e74705SXin Li  // CHECK: call void @llvm.lifetime.end
196*67e74705SXin Li  // CHECK: call void @objc_release
197*67e74705SXin Li  // CHECK: call void @llvm.lifetime.end
198*67e74705SXin Li  // CHECK-NEXT: ret void
199*67e74705SXin Li}
200*67e74705SXin Li
201*67e74705SXin Li// rdar://problem/9603128
202*67e74705SXin Li// CHECK-LABEL: define i8* @_Z6test36P11objc_object(
203*67e74705SXin Liid test36(id z) {
204*67e74705SXin Li  // CHECK: objc_retain
205*67e74705SXin Li  // CHECK: objc_retain
206*67e74705SXin Li  // CHECK: objc_release
207*67e74705SXin Li  // CHECK: objc_autoreleaseReturnValue
208*67e74705SXin Li  return z;
209*67e74705SXin Li}
210*67e74705SXin Li
211*67e74705SXin Li// Template instantiation side of rdar://problem/9817306
212*67e74705SXin Li@interface Test37
213*67e74705SXin Li+ alloc;
214*67e74705SXin Li- init;
215*67e74705SXin Li- (NSArray *) array;
216*67e74705SXin Li@end
217*67e74705SXin Litemplate <class T> void test37(T *a) {
218*67e74705SXin Li  for (id x in a.array) {
219*67e74705SXin Li    use(x);
220*67e74705SXin Li  }
221*67e74705SXin Li}
222*67e74705SXin Liextern template void test37<Test37>(Test37 *a);
223*67e74705SXin Litemplate void test37<Test37>(Test37 *a);
224*67e74705SXin Li// CHECK-LABEL: define weak_odr void @_Z6test37I6Test37EvPT_(
225*67e74705SXin Li// CHECK:      [[T0:%.*]] = call [[NSARRAY]]* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to [[NSARRAY]]* (i8*, i8*)*)(
226*67e74705SXin Li// CHECK-NEXT: [[T1:%.*]] = bitcast [[NSARRAY]]* [[T0]] to i8*
227*67e74705SXin Li// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
228*67e74705SXin Li// CHECK-NEXT: [[COLL:%.*]] = bitcast i8* [[T2]] to [[NSARRAY]]*
229*67e74705SXin Li
230*67e74705SXin Li// Make sure it's not immediately released before starting the iteration.
231*67e74705SXin Li// CHECK-NEXT: load i8*, i8** @OBJC_SELECTOR_REFERENCES_
232*67e74705SXin Li// CHECK-NEXT: [[T0:%.*]] = bitcast [[NSARRAY]]* [[COLL]] to i8*
233*67e74705SXin Li// CHECK-NEXT: @objc_msgSend
234*67e74705SXin Li
235*67e74705SXin Li// This bitcast is for the mutation check.
236*67e74705SXin Li// CHECK:      [[T0:%.*]] = bitcast [[NSARRAY]]* [[COLL]] to i8*
237*67e74705SXin Li// CHECK-NEXT: @objc_enumerationMutation
238*67e74705SXin Li
239*67e74705SXin Li// This bitcast is for the 'next' message send.
240*67e74705SXin Li// CHECK:      [[T0:%.*]] = bitcast [[NSARRAY]]* [[COLL]] to i8*
241*67e74705SXin Li// CHECK-NEXT: @objc_msgSend
242*67e74705SXin Li
243*67e74705SXin Li// This bitcast is for the final release.
244*67e74705SXin Li// CHECK:      [[T0:%.*]] = bitcast [[NSARRAY]]* [[COLL]] to i8*
245*67e74705SXin Li// CHECK-NEXT: call void @objc_release(i8* [[T0]])
246*67e74705SXin Li
247*67e74705SXin Litemplate<typename T>
248*67e74705SXin Livoid send_release() {
249*67e74705SXin Li  [Test37 array];
250*67e74705SXin Li}
251*67e74705SXin Li
252*67e74705SXin Li// CHECK-LABEL: define weak_odr void @_Z12send_releaseIiEvv(
253*67e74705SXin Li// CHECK: call %0* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend
254*67e74705SXin Li// CHECK-NEXT: bitcast
255*67e74705SXin Li// CHECK-NEXT: call i8* @objc_retainAutoreleasedReturnValue
256*67e74705SXin Li// CHECK-NEXT: bitcast
257*67e74705SXin Li// CHECK-NEXT: bitcast
258*67e74705SXin Li// CHECK-NEXT: call void @objc_release
259*67e74705SXin Li// CHECK-NEXT: ret void
260*67e74705SXin Litemplate void send_release<int>();
261*67e74705SXin Li
262*67e74705SXin Litemplate<typename T>
263*67e74705SXin LiTest37 *instantiate_init() {
264*67e74705SXin Li  Test37 *result = [[Test37 alloc] init];
265*67e74705SXin Li  return result;
266*67e74705SXin Li}
267*67e74705SXin Li
268*67e74705SXin Li// CHECK-LABEL: define weak_odr %2* @_Z16instantiate_initIiEP6Test37v
269*67e74705SXin Li// CHECK: call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend
270*67e74705SXin Li// CHECK: call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend
271*67e74705SXin Li// CHECK: call i8* @objc_retain
272*67e74705SXin Li// CHECK: call void @objc_release
273*67e74705SXin Li// CHECK: call i8* @objc_autoreleaseReturnValue
274*67e74705SXin Litemplate Test37* instantiate_init<int>();
275*67e74705SXin Li
276*67e74705SXin Li// Just make sure that the AST invariants hold properly here,
277*67e74705SXin Li// i.e. that we don't crash.
278*67e74705SXin Li// The block should get bound in the full-expression outside
279*67e74705SXin Li// the statement-expression.
280*67e74705SXin Litemplate <class T> class Test38 {
281*67e74705SXin Li  void test(T x) {
282*67e74705SXin Li    ^{ (void) x; }, ({ x; });
283*67e74705SXin Li  }
284*67e74705SXin Li};
285*67e74705SXin Li// CHECK-LABEL: define weak_odr void @_ZN6Test38IiE4testEi(
286*67e74705SXin Litemplate class Test38<int>;
287*67e74705SXin Li
288*67e74705SXin Li// rdar://problem/11964832
289*67e74705SXin Liclass Test39_base1 {
290*67e74705SXin Li  virtual void foo();
291*67e74705SXin Li};
292*67e74705SXin Liclass Test39_base2 {
293*67e74705SXin Li  virtual id bar();
294*67e74705SXin Li};
295*67e74705SXin Liclass Test39 : Test39_base1, Test39_base2 { // base2 is at non-zero offset
296*67e74705SXin Li  virtual id bar();
297*67e74705SXin Li};
298*67e74705SXin Liid Test39::bar() { return 0; }
299*67e74705SXin Li// Note lack of autorelease.
300*67e74705SXin Li// CHECK-LABEL:    define i8* @_ZThn8_N6Test393barEv(
301*67e74705SXin Li// CHECK:      call i8* @_ZN6Test393barEv(
302*67e74705SXin Li// CHECK-NEXT: ret i8*
303*67e74705SXin Li
304*67e74705SXin Li// rdar://13617051
305*67e74705SXin Li// Just a basic sanity-check that IR-gen still works after instantiating
306*67e74705SXin Li// a non-dependent message send that requires writeback.
307*67e74705SXin Li@interface Test40
308*67e74705SXin Li+ (void) foo:(id *)errorPtr;
309*67e74705SXin Li@end
310*67e74705SXin Litemplate <class T> void test40_helper() {
311*67e74705SXin Li  id x;
312*67e74705SXin Li  [Test40 foo: &x];
313*67e74705SXin Li};
314*67e74705SXin Litemplate void test40_helper<int>();
315*67e74705SXin Li// CHECK-LABEL:    define weak_odr void @_Z13test40_helperIiEvv()
316*67e74705SXin Li// CHECK:      [[X:%.*]] = alloca i8*
317*67e74705SXin Li// CHECK-NEXT: [[TEMP:%.*]] = alloca i8*
318*67e74705SXin Li// CHECK-NEXT: [[XP:%.*]] = bitcast i8** [[X]] to i8*
319*67e74705SXin Li// CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[XP]])
320*67e74705SXin Li// CHECK-NEXT: store i8* null, i8** [[X]]
321*67e74705SXin Li// CHECK:      [[T0:%.*]] = load i8*, i8** [[X]]
322*67e74705SXin Li// CHECK-NEXT: store i8* [[T0]], i8** [[TEMP]]
323*67e74705SXin Li// CHECK:      @objc_msgSend
324*67e74705SXin Li// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[TEMP]]
325*67e74705SXin Li// CHECK-NEXT: call i8* @objc_retain(i8* [[T0]])
326*67e74705SXin Li
327*67e74705SXin Li// Check that moves out of __weak variables are compiled to use objc_moveWeak.
328*67e74705SXin Livoid test41(__weak id &&x) {
329*67e74705SXin Li  __weak id y = static_cast<__weak id &&>(x);
330*67e74705SXin Li}
331*67e74705SXin Li// CHECK-LABEL: define void @_Z6test41OU6__weakP11objc_object
332*67e74705SXin Li// CHECK:      [[X:%.*]] = alloca i8**
333*67e74705SXin Li// CHECK:      [[Y:%.*]] = alloca i8*
334*67e74705SXin Li// CHECK:      [[T0:%.*]] = load i8**, i8*** [[X]]
335*67e74705SXin Li// CHECK-NEXT: call void @objc_moveWeak(i8** [[Y]], i8** [[T0]])
336*67e74705SXin Li// CHECK-NEXT: call void @objc_destroyWeak(i8** [[Y]])
337