1 // RUN: %clang_cc1 -emit-llvm -fobjc-arc -triple x86_64-apple-darwin10 %s -o - | FileCheck %s
3 struct my_complex_struct {
7 struct my_aggregate_struct {
12 __attribute__((objc_root_class))
14 - (int)getInt __attribute__((objc_direct));
15 @property(direct, readonly) int intProperty;
16 @property(direct, readonly) int intProperty2;
17 @property(direct, readonly) id objectProperty;
21 // CHECK-LABEL: define hidden i32 @"\01-[Root intProperty2]"
26 // CHECK-LABEL: define hidden i32 @"\01-[Root getInt]"(
27 - (int)getInt __attribute__((objc_direct)) {
29 // CHECK-LABEL: entry:
30 // CHECK-NEXT: [[RETVAL:%.*]] = alloca
31 // CHECK-NEXT: [[SELFADDR:%.*]] = alloca ptr,
32 // CHECK-NEXT: store ptr %{{.*}}, ptr [[SELFADDR]],
35 // CHECK-NEXT: [[SELF:%.*]] = load ptr, ptr [[SELFADDR]],
36 // CHECK-NEXT: [[NILCHECK:%.*]] = icmp eq ptr [[SELF]], null
37 // CHECK-NEXT: br i1 [[NILCHECK]],
39 // setting return value to nil
40 // CHECK-LABEL: objc_direct_method.self_is_nil:
41 // CHECK-NEXT: call void @llvm.memset{{[^(]*}}({{[^,]*}}[[RETVAL]], i8 0,
42 // CHECK-NEXT: br label
45 // CHECK-LABEL: objc_direct_method.cont:
46 // CHECK: store{{.*}}[[RETVAL]],
47 // CHECK-NEXT: br label
50 // CHECK-LABEL: return:
51 // CHECK: {{%.*}} = load{{.*}}[[RETVAL]],
56 // CHECK-LABEL: define hidden i32 @"\01+[Root classGetInt]"(
57 + (int)classGetInt __attribute__((objc_direct)) {
59 // CHECK-LABEL: entry:
60 // CHECK-NEXT: [[SELFADDR:%.*]] = alloca ptr,
61 // CHECK-NEXT: store ptr %{{.*}}, ptr [[SELFADDR]],
64 // CHECK-NEXT: [[SELF:%.*]] = load ptr, ptr [[SELFADDR]],
65 // CHECK-NEXT: [[SELFSEL:%.*]] = load ptr, ptr @OBJC_SELECTOR_REFERENCES_
66 // CHECK-NEXT: [[SELF0:%.*]] = call {{.*}} @objc_msgSend
67 // CHECK-NEXT: store ptr [[SELF0]], ptr [[SELFADDR]],
74 // CHECK-LABEL: define hidden i64 @"\01-[Root getComplex]"(
75 - (struct my_complex_struct)getComplex __attribute__((objc_direct)) {
77 // CHECK-LABEL: entry:
78 // CHECK-NEXT: [[RETVAL:%.*]] = alloca
79 // CHECK-NEXT: [[SELFADDR:%.*]] = alloca ptr,
80 // CHECK-NEXT: store ptr %{{.*}}, ptr [[SELFADDR]],
83 // CHECK-NEXT: [[SELF:%.*]] = load ptr, ptr [[SELFADDR]],
84 // CHECK-NEXT: [[NILCHECK:%.*]] = icmp eq ptr [[SELF]], null
85 // CHECK-NEXT: br i1 [[NILCHECK]],
87 // setting return value to nil
88 // CHECK-LABEL: objc_direct_method.self_is_nil:
89 // CHECK-NEXT: call void @llvm.memset{{[^(]*}}({{[^,]*}}[[RETVAL]], i8 0,
90 // CHECK-NEXT: br label
93 // CHECK-LABEL: objc_direct_method.cont:
94 // CHECK-NEXT: call void @llvm.memcpy{{[^(]*}}({{[^,]*}}[[RETVAL]],
95 // CHECK-NEXT: br label
98 // CHECK-LABEL: return:
99 // CHECK-NEXT: {{%.*}} = load{{.*}}[[RETVAL]],
101 struct my_complex_struct st = {.a = 42};
105 // CHECK-LABEL: define hidden i64 @"\01+[Root classGetComplex]"(
106 + (struct my_complex_struct)classGetComplex __attribute__((objc_direct)) {
107 struct my_complex_struct st = {.a = 42};
112 // CHECK-LABEL: define hidden void @"\01-[Root getAggregate]"(
113 - (struct my_aggregate_struct)getAggregate __attribute__((objc_direct)) {
114 // CHECK: ptr noalias sret(%struct.my_aggregate_struct) align 4 [[RETVAL:%[^,]*]],
116 // loading parameters
117 // CHECK-LABEL: entry:
118 // CHECK-NEXT: [[SELFADDR:%.*]] = alloca ptr,
119 // CHECK-NEXT: store ptr %{{.*}}, ptr [[SELFADDR]],
122 // CHECK-NEXT: [[SELF:%.*]] = load ptr, ptr [[SELFADDR]],
123 // CHECK-NEXT: [[NILCHECK:%.*]] = icmp eq ptr [[SELF]], null
124 // CHECK-NEXT: br i1 [[NILCHECK]],
126 // setting return value to nil
127 // CHECK-LABEL: objc_direct_method.self_is_nil:
128 // CHECK-NEXT: call void @llvm.memset{{[^(]*}}({{[^,]*}}[[RETVAL]], i8 0,
129 // CHECK-NEXT: br label
132 // CHECK-LABEL: objc_direct_method.cont:
136 // CHECK-LABEL: return:
138 struct my_aggregate_struct st = {.a = 42};
142 // CHECK-LABEL: define hidden void @"\01+[Root classGetAggregate]"(
143 + (struct my_aggregate_struct)classGetAggregate __attribute__((objc_direct)) {
144 struct my_aggregate_struct st = {.a = 42};
149 // CHECK-LABEL: define hidden void @"\01-[Root accessCmd]"(
150 - (void)accessCmd __attribute__((objc_direct)) {
151 // CHECK-LABEL: entry:
152 // CHECK-NEXT: [[SELFADDR:%.*]] = alloca ptr,
153 // CHECK-NEXT: [[CMDVAL:%_cmd]] = alloca ptr,
155 // loading the _cmd selector
156 // CHECK-LABEL: objc_direct_method.cont:
157 // CHECK-NEXT: [[CMD1:%.*]] = load ptr, ptr @OBJC_SELECTOR_REFERENCES_
158 // CHECK-NEXT: store ptr [[CMD1]], ptr [[CMDVAL]],
163 // CHECK-LABEL: define hidden i32 @"\01-[Root intProperty]"
165 // Check the synthesized objectProperty calls objc_getProperty(); this also
166 // checks that the synthesized method passes undef for the `cmd` argument.
167 // CHECK-LABEL: define hidden ptr @"\01-[Root objectProperty]"(
168 // CHECK-LABEL: objc_direct_method.cont:
169 // CHECK-NEXT: [[SELFVAL:%.*]] = load {{.*}} %self.addr,
170 // CHECK-NEXT: [[IVAR:%.*]] = load {{.*}} @"OBJC_IVAR_$_Root._objectProperty",
171 // CHECK-NEXT: call ptr @objc_getProperty(ptr noundef [[SELFVAL]], ptr noundef poison, i64 noundef [[IVAR]], {{.*}})
173 @interface Foo : Root {
174 id __strong _cause_cxx_destruct;
176 @property(nonatomic, readonly, direct) int getDirect_setDynamic;
177 @property(nonatomic, readonly) int getDynamic_setDirect;
181 @property(nonatomic, readwrite) int getDirect_setDynamic;
182 @property(nonatomic, readwrite, direct) int getDynamic_setDirect;
183 - (int)directMethodInExtension __attribute__((objc_direct));
187 - (int)directMethodInCategory __attribute__((objc_direct));
190 __attribute__((objc_direct_members))
192 // CHECK-LABEL: define hidden i32 @"\01-[Foo directMethodInExtension]"(
193 - (int)directMethodInExtension {
196 // CHECK-LABEL: define hidden i32 @"\01-[Foo getDirect_setDynamic]"(
197 // CHECK-LABEL: define internal void @"\01-[Foo setGetDirect_setDynamic:]"(
198 // CHECK-LABEL: define internal i32 @"\01-[Foo getDynamic_setDirect]"(
199 // CHECK-LABEL: define hidden void @"\01-[Foo setGetDynamic_setDirect:]"(
200 // CHECK-LABEL: define internal void @"\01-[Foo .cxx_destruct]"(
203 @implementation Foo (Cat)
204 // CHECK-LABEL: define hidden i32 @"\01-[Foo directMethodInCategory]"(
205 - (int)directMethodInCategory {
208 // CHECK-LABEL: define hidden i32 @"\01-[Foo directMethodInCategoryNoDecl]"(
209 - (int)directMethodInCategoryNoDecl __attribute__((objc_direct)) {
214 int useRoot(Root *r) {
215 // CHECK-LABEL: define{{.*}} i32 @useRoot
216 // CHECK: %{{[^ ]*}} = call i32 @"\01-[Root getInt]"
217 // CHECK: %{{[^ ]*}} = call i32 @"\01-[Root intProperty]"
218 // CHECK: %{{[^ ]*}} = call i32 @"\01-[Root intProperty2]"
219 return [r getInt] + [r intProperty] + [r intProperty2];
223 // CHECK-LABEL: define{{.*}} i32 @useFoo
224 // CHECK: call void @"\01-[Foo setGetDynamic_setDirect:]"
225 // CHECK: %{{[^ ]*}} = call i32 @"\01-[Foo getDirect_setDynamic]"
226 // CHECK: %{{[^ ]*}} = call i32 @"\01-[Foo directMethodInExtension]"
227 // CHECK: %{{[^ ]*}} = call i32 @"\01-[Foo directMethodInCategory]"
228 // CHECK: %{{[^ ]*}} = call i32 @"\01-[Foo directMethodInCategoryNoDecl]"
229 [f setGetDynamic_setDirect:1];
230 return [f getDirect_setDynamic] +
231 [f directMethodInExtension] +
232 [f directMethodInCategory] +
233 [f directMethodInCategoryNoDecl];
236 __attribute__((objc_root_class))
237 @interface RootDeclOnly
238 @property(direct, readonly) int intProperty;
241 int useRootDeclOnly(RootDeclOnly *r) {
242 // CHECK-LABEL: define{{.*}} i32 @useRootDeclOnly
243 // CHECK: %{{[^ ]*}} = call i32 @"\01-[RootDeclOnly intProperty]"
244 return [r intProperty];