xref: /aosp_15_r20/external/clang/test/CodeGenObjCXX/arc-references.mm (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li// RUN: %clang_cc1 -std=c++11 -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 Li@interface A
4*67e74705SXin Li@end
5*67e74705SXin Li
6*67e74705SXin Liid getObject();
7*67e74705SXin Livoid callee();
8*67e74705SXin Li
9*67e74705SXin Li// Lifetime extension for binding a reference to an rvalue
10*67e74705SXin Li// CHECK-LABEL: define void @_Z5test0v()
11*67e74705SXin Livoid test0() {
12*67e74705SXin Li  // CHECK: call i8* @_Z9getObjectv
13*67e74705SXin Li  // CHECK-NEXT: call i8* @objc_retainAutoreleasedReturnValue
14*67e74705SXin Li  const __strong id &ref1 = getObject();
15*67e74705SXin Li  // CHECK: call void @_Z6calleev
16*67e74705SXin Li  callee();
17*67e74705SXin Li  // CHECK: call i8* @_Z9getObjectv
18*67e74705SXin Li  // CHECK-NEXT: call i8* @objc_retainAutoreleasedReturnValue
19*67e74705SXin Li  // CHECK-NEXT: call i8* @objc_autorelease
20*67e74705SXin Li  const __autoreleasing id &ref2 = getObject();
21*67e74705SXin Li  // CHECK: call void @_Z6calleev
22*67e74705SXin Li  callee();
23*67e74705SXin Li  // CHECK: call void @objc_release
24*67e74705SXin Li  // CHECK-NEXT: ret
25*67e74705SXin Li}
26*67e74705SXin Li
27*67e74705SXin Li// No lifetime extension when we're binding a reference to an lvalue.
28*67e74705SXin Li// CHECK-LABEL: define void @_Z5test1RU8__strongP11objc_objectRU6__weakS0_
29*67e74705SXin Livoid test1(__strong id &x, __weak id &y) {
30*67e74705SXin Li  // CHECK-NOT: release
31*67e74705SXin Li  const __strong id &ref1 = x;
32*67e74705SXin Li  const __autoreleasing id &ref2 = x;
33*67e74705SXin Li  const __weak id &ref3 = y;
34*67e74705SXin Li  // CHECK: ret void
35*67e74705SXin Li}
36*67e74705SXin Li
37*67e74705SXin Litypedef __strong id strong_id;
38*67e74705SXin Li
39*67e74705SXin Li//CHECK: define void @_Z5test3v
40*67e74705SXin Livoid test3() {
41*67e74705SXin Li  // CHECK: [[REF:%.*]] = alloca i8**, align 8
42*67e74705SXin Li  // CHECK: call i8* @objc_initWeak
43*67e74705SXin Li  // CHECK-NEXT: store i8**
44*67e74705SXin Li  const __weak id &ref = strong_id();
45*67e74705SXin Li  // CHECK-NEXT: call void @_Z6calleev()
46*67e74705SXin Li  callee();
47*67e74705SXin Li  // CHECK-NEXT: [[PTR:%.*]] = bitcast i8*** [[REF]] to i8*
48*67e74705SXin Li  // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PTR]])
49*67e74705SXin Li  // CHECK-NEXT: call void @objc_destroyWeak
50*67e74705SXin Li  // CHECK-NEXT: ret void
51*67e74705SXin Li}
52*67e74705SXin Li
53*67e74705SXin Li// CHECK-LABEL: define void @_Z5test4RU8__strongP11objc_object
54*67e74705SXin Livoid test4(__strong id &x) {
55*67e74705SXin Li  // CHECK: call i8* @objc_retain
56*67e74705SXin Li  __strong A* const &ar = x;
57*67e74705SXin Li  // CHECK: store i32 17, i32*
58*67e74705SXin Li  int i = 17;
59*67e74705SXin Li  // CHECK: call void @objc_release(
60*67e74705SXin Li  // CHECK: ret void
61*67e74705SXin Li}
62*67e74705SXin Li
63*67e74705SXin Livoid sink(__strong A* &&);
64*67e74705SXin Li
65*67e74705SXin Li// CHECK-LABEL: define void @_Z5test5RU8__strongP11objc_object
66*67e74705SXin Livoid test5(__strong id &x) {
67*67e74705SXin Li  // CHECK:      [[REFTMP:%.*]] = alloca {{%.*}}*, align 8
68*67e74705SXin Li  // CHECK:      [[I:%.*]] = alloca i32, align 4
69*67e74705SXin Li  // CHECK:      [[OBJ_ID:%.*]] = call i8* @objc_retain(
70*67e74705SXin Li  // CHECK-NEXT: [[OBJ_A:%.*]] = bitcast i8* [[OBJ_ID]] to [[A:%[a-zA-Z0-9]+]]*
71*67e74705SXin Li  // CHECK-NEXT: store [[A]]* [[OBJ_A]], [[A]]** [[REFTMP:%[a-zA-Z0-9]+]]
72*67e74705SXin Li  // CHECK-NEXT: call void @_Z4sinkOU8__strongP1A
73*67e74705SXin Li  sink(x);
74*67e74705SXin Li  // CHECK-NEXT: [[OBJ_A:%[a-zA-Z0-9]+]] = load [[A]]*, [[A]]** [[REFTMP]]
75*67e74705SXin Li  // CHECK-NEXT: [[OBJ_ID:%[a-zA-Z0-9]+]] = bitcast [[A]]* [[OBJ_A]] to i8*
76*67e74705SXin Li  // CHECK-NEXT: call void @objc_release
77*67e74705SXin Li  // CHECK-NEXT: [[IPTR1:%.*]] = bitcast i32* [[I]] to i8*
78*67e74705SXin Li  // CHECK-NEXT: call void @llvm.lifetime.start(i64 4, i8* [[IPTR1]])
79*67e74705SXin Li  // CHECK-NEXT: store i32 17, i32
80*67e74705SXin Li  int i = 17;
81*67e74705SXin Li  // CHECK-NEXT: [[IPTR2:%.*]] = bitcast i32* [[I]] to i8*
82*67e74705SXin Li  // CHECK-NEXT: call void @llvm.lifetime.end(i64 4, i8* [[IPTR2]])
83*67e74705SXin Li  // CHECK-NEXT: ret void
84*67e74705SXin Li}
85*67e74705SXin Li
86*67e74705SXin Li// CHECK-LABEL: define internal void @__cxx_global_var_init(
87*67e74705SXin Li// CHECK: call i8* @_Z9getObjectv
88*67e74705SXin Li// CHECK-NEXT: call i8* @objc_retainAutoreleasedReturnValue
89*67e74705SXin Liconst __strong id &global_ref = getObject();
90*67e74705SXin Li
91*67e74705SXin Li// Note: we intentionally don't release the object.
92*67e74705SXin Li
93