xref: /llvm-project/clang/test/CodeGenObjC/arc-property.m (revision 0f1c1be1968076d6f96f8a7bcc4a15cf195ecd97)
1// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-arc -emit-llvm %s -o - | FileCheck %s
2
3@interface Test0
4- (void) setValue: (id) x;
5@end
6void test0(Test0 *t0, id value) {
7  t0.value = value;
8}
9// CHECK-LABEL: define{{.*}} void @test0(
10// CHECK: call void @llvm.objc.storeStrong
11// CHECK: call void @llvm.objc.storeStrong
12// CHECK: @objc_msgSend
13// CHECK: call void @llvm.objc.storeStrong(
14// CHECK: call void @llvm.objc.storeStrong(
15
16struct S1 { Class isa; };
17@interface Test1
18@property (nonatomic, strong) __attribute__((NSObject)) struct S1 *pointer;
19@end
20@implementation Test1
21@synthesize pointer;
22@end
23//   The getter should be a simple load.
24// CHECK:    define internal ptr @"\01-[Test1 pointer]"(
25// CHECK:      [[OFFSET:%.*]] = load i64, ptr @"OBJC_IVAR_$_Test1.pointer"
26// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, ptr {{%.*}}, i64 [[OFFSET]]
27// CHECK-NEXT: [[T3:%.*]] = load ptr, ptr [[T1]], align 8
28// CHECK-NEXT: ret ptr [[T3]]
29
30//   The setter should be using objc_setProperty.
31// CHECK:    define internal void @"\01-[Test1 setPointer:]"(
32// CHECK: [[OFFSET:%.*]] = load i64, ptr @"OBJC_IVAR_$_Test1.pointer"
33// CHECK-NEXT: [[T1:%.*]] = load ptr, ptr {{%.*}}
34// CHECK-NEXT: call void @objc_setProperty(ptr noundef {{%.*}}, ptr noundef {{%.*}}, i64 noundef [[OFFSET]], ptr noundef [[T1]], i1 noundef zeroext false, i1 noundef zeroext false)
35// CHECK-NEXT: ret void
36
37
38@interface Test2 {
39@private
40  Class _theClass;
41}
42@property (copy) Class theClass;
43@end
44
45static Class theGlobalClass;
46@implementation Test2
47@synthesize theClass = _theClass;
48- (void) test {
49  _theClass = theGlobalClass;
50}
51@end
52// CHECK:    define internal void @"\01-[Test2 test]"(
53// CHECK:      [[T0:%.*]] = load ptr, ptr @theGlobalClass, align 8
54// CHECK-NEXT: [[T1:%.*]] = load ptr, ptr
55// CHECK-NEXT: [[OFFSET:%.*]] = load i64, ptr @"OBJC_IVAR_$_Test2._theClass"
56// CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8, ptr [[T1]], i64 [[OFFSET]]
57// CHECK-NEXT: call void @llvm.objc.storeStrong(ptr [[T3]], ptr [[T0]]) [[NUW:#[0-9]+]]
58// CHECK-NEXT: ret void
59
60// CHECK:    define internal ptr @"\01-[Test2 theClass]"(
61// CHECK:      [[OFFSET:%.*]] = load i64, ptr @"OBJC_IVAR_$_Test2._theClass"
62// CHECK-NEXT: [[T0:%.*]] = tail call ptr @objc_getProperty(ptr noundef {{.*}}, ptr noundef {{.*}}, i64 noundef [[OFFSET]], i1 noundef zeroext true)
63// CHECK-NEXT: ret ptr [[T0]]
64
65// CHECK:    define internal void @"\01-[Test2 setTheClass:]"(
66// CHECK: [[OFFSET:%.*]] = load i64, ptr @"OBJC_IVAR_$_Test2._theClass"
67// CHECK-NEXT: [[T1:%.*]] = load ptr, ptr {{%.*}}
68// CHECK-NEXT: call void @objc_setProperty(ptr noundef {{%.*}}, ptr noundef {{%.*}}, i64 noundef [[OFFSET]], ptr noundef [[T1]], i1 noundef zeroext true, i1 noundef zeroext true)
69// CHECK-NEXT: ret void
70
71// CHECK:    define internal void @"\01-[Test2 .cxx_destruct]"(
72// CHECK:      [[T0:%.*]] = load ptr, ptr
73// CHECK-NEXT: [[OFFSET:%.*]] = load i64, ptr @"OBJC_IVAR_$_Test2._theClass"
74// CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds i8, ptr [[T0]], i64 [[OFFSET]]
75// CHECK-NEXT: call void @llvm.objc.storeStrong(ptr [[T2]], ptr null) [[NUW]]
76// CHECK-NEXT: ret void
77
78@interface Test3
79@property id copyMachine;
80@end
81
82void test3(Test3 *t) {
83  id x = t.copyMachine;
84  x = [t copyMachine];
85}
86// CHECK:    define{{.*}} void @test3(ptr
87//   Prologue.
88// CHECK:      [[T:%.*]] = alloca ptr,
89// CHECK-NEXT: [[X:%.*]] = alloca ptr,
90//   Property access.
91// CHECK:      [[T0:%.*]] = load ptr, ptr [[T]],
92// CHECK-NEXT: [[SEL:%.*]] = load ptr, ptr @OBJC_SELECTOR_REFERENCES
93// CHECK-NEXT: [[T2:%.*]] = call ptr @objc_msgSend(ptr noundef [[T0]], ptr noundef [[SEL]])
94// CHECK-NEXT: store ptr [[T2]], ptr [[X]],
95//   Message send.
96// CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[T]],
97// CHECK-NEXT: [[SEL:%.*]] = load ptr, ptr @OBJC_SELECTOR_REFERENCES
98// CHECK-NEXT: [[T2:%.*]] = call ptr @objc_msgSend(ptr noundef [[T0]], ptr noundef [[SEL]])
99// CHECK-NEXT: [[T3:%.*]] = load ptr, ptr [[X]],
100// CHECK-NEXT: store ptr [[T2]], ptr [[X]],
101// CHECK-NEXT: call void @llvm.objc.release(ptr [[T3]])
102//   Epilogue.
103// CHECK-NEXT: call void @llvm.objc.storeStrong(ptr [[X]], ptr null)
104// CHECK-NEXT: call void @llvm.objc.storeStrong(ptr [[T]], ptr null)
105// CHECK-NEXT: ret void
106
107@implementation Test3
108- (id) copyMachine {
109  extern id test3_helper(void);
110  return test3_helper();
111}
112// CHECK:    define internal ptr @"\01-[Test3 copyMachine]"(
113// CHECK:      [[T0:%.*]] = call ptr @test3_helper()
114// CHECK-NEXT: [[T1:%.*]] = notail call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr [[T0]])
115// CHECK-NEXT: ret ptr [[T1]]
116- (void) setCopyMachine: (id) x {}
117@end
118
119// When synthesizing a property that's declared in multiple protocols, ensure
120// that the setter is emitted if any of these declarations is readwrite.
121@protocol ABC
122@property (copy, nonatomic,  readonly) Test3 *someId;
123@end
124@protocol ABC__Mutable <ABC>
125@property (copy, nonatomic, readwrite) Test3 *someId;
126@end
127
128@interface ABC_Class <ABC, ABC__Mutable>
129@end
130
131@implementation ABC_Class
132@synthesize someId = _someId;
133// CHECK:  define internal ptr @"\01-[ABC_Class someId]"
134// CHECK:  define internal void @"\01-[ABC_Class setSomeId:]"(
135@end
136
137
138// CHECK: attributes [[NUW]] = { nounwind }
139