xref: /aosp_15_r20/external/clang/test/CodeGenObjC/property.m (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm -o - %s | FileCheck %s
2*67e74705SXin Li
3*67e74705SXin Li// TODO: actually test most of this instead of just emitting it
4*67e74705SXin Li
5*67e74705SXin Liint printf(const char *, ...);
6*67e74705SXin Li
7*67e74705SXin Li@interface Root
8*67e74705SXin Li-(id) alloc;
9*67e74705SXin Li-(id) init;
10*67e74705SXin Li@end
11*67e74705SXin Li
12*67e74705SXin Li@interface A : Root {
13*67e74705SXin Li  int x;
14*67e74705SXin Li  int y, ro, z;
15*67e74705SXin Li  id ob0, ob1, ob2, ob3, ob4;
16*67e74705SXin Li}
17*67e74705SXin Li@property int x;
18*67e74705SXin Li@property int y;
19*67e74705SXin Li@property int z;
20*67e74705SXin Li@property(readonly) int ro;
21*67e74705SXin Li@property(assign) id ob0;
22*67e74705SXin Li@property(retain) id ob1;
23*67e74705SXin Li@property(copy) id ob2;
24*67e74705SXin Li@property(retain, nonatomic) id ob3;
25*67e74705SXin Li@property(copy, nonatomic) id ob4;
26*67e74705SXin Li@end
27*67e74705SXin Li
28*67e74705SXin Li@implementation A
29*67e74705SXin Li@dynamic x;
30*67e74705SXin Li@synthesize y;
31*67e74705SXin Li@synthesize z = z;
32*67e74705SXin Li@synthesize ro;
33*67e74705SXin Li@synthesize ob0;
34*67e74705SXin Li@synthesize ob1;
35*67e74705SXin Li@synthesize ob2;
36*67e74705SXin Li@synthesize ob3;
37*67e74705SXin Li@synthesize ob4;
38*67e74705SXin Li-(int) y {
39*67e74705SXin Li  return x + 1;
40*67e74705SXin Li}
41*67e74705SXin Li-(void) setZ: (int) arg {
42*67e74705SXin Li  x = arg - 1;
43*67e74705SXin Li}
44*67e74705SXin Li@end
45*67e74705SXin Li
46*67e74705SXin Li@interface A (Cat)
47*67e74705SXin Li@property int dyn;
48*67e74705SXin Li@end
49*67e74705SXin Li
50*67e74705SXin Li@implementation A (Cat)
51*67e74705SXin Li-(int) dyn {
52*67e74705SXin Li  return 10;
53*67e74705SXin Li}
54*67e74705SXin Li@end
55*67e74705SXin Li
56*67e74705SXin Li// Test that compound operations only compute the base once.
57*67e74705SXin Li// CHECK-LABEL: define void @test2
58*67e74705SXin LiA *test2_helper(void);
59*67e74705SXin Livoid test2() {
60*67e74705SXin Li  // CHECK:      [[BASE:%.*]] = call [[A:%.*]]* @test2_helper()
61*67e74705SXin Li  // CHECK-NEXT: [[SEL:%.*]] = load i8*, i8**
62*67e74705SXin Li  // CHECK-NEXT: [[BASETMP:%.*]] = bitcast [[A]]* [[BASE]] to i8*
63*67e74705SXin Li  // CHECK-NEXT: [[LD:%.*]] = call i32 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i32 (i8*, i8*)*)(i8* [[BASETMP]], i8* [[SEL]])
64*67e74705SXin Li  // CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[LD]], 1
65*67e74705SXin Li  // CHECK-NEXT: [[SEL:%.*]] = load i8*, i8**
66*67e74705SXin Li  // CHECK-NEXT: [[BASETMP:%.*]] = bitcast [[A]]* [[BASE]] to i8*
67*67e74705SXin Li  // CHECK-NEXT: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i32)*)(i8* [[BASETMP]], i8* [[SEL]], i32 [[ADD]])
68*67e74705SXin Li  test2_helper().dyn++;
69*67e74705SXin Li
70*67e74705SXin Li  // CHECK:      [[BASE:%.*]] = call [[A]]* @test2_helper()
71*67e74705SXin Li  // CHECK-NEXT: [[SEL:%.*]] = load i8*, i8**
72*67e74705SXin Li  // CHECK-NEXT: [[BASETMP:%.*]] = bitcast [[A]]* [[BASE]] to i8*
73*67e74705SXin Li  // CHECK-NEXT: [[LD:%.*]] = call i32 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i32 (i8*, i8*)*)(i8* [[BASETMP]], i8* [[SEL]])
74*67e74705SXin Li  // CHECK-NEXT: [[ADD:%.*]] = mul nsw i32 [[LD]], 10
75*67e74705SXin Li  // CHECK-NEXT: [[SEL:%.*]] = load i8*, i8**
76*67e74705SXin Li  // CHECK-NEXT: [[BASETMP:%.*]] = bitcast [[A]]* [[BASE]] to i8*
77*67e74705SXin Li  // CHECK-NEXT: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i32)*)(i8* [[BASETMP]], i8* [[SEL]], i32 [[ADD]])
78*67e74705SXin Li  test2_helper().dyn *= 10;
79*67e74705SXin Li}
80*67e74705SXin Li
81*67e74705SXin Li// Test aggregate initialization from property reads.
82*67e74705SXin Li// Not crashing is good enough for the property-specific test.
83*67e74705SXin Listruct test3_struct { int x,y,z; };
84*67e74705SXin Listruct test3_nested { struct test3_struct t; };
85*67e74705SXin Li@interface test3_object
86*67e74705SXin Li@property struct test3_struct s;
87*67e74705SXin Li@end
88*67e74705SXin Livoid test3(test3_object *p) {
89*67e74705SXin Li  struct test3_struct array[1] = { p.s };
90*67e74705SXin Li  struct test3_nested agg = { p.s };
91*67e74705SXin Li}
92*67e74705SXin Li
93*67e74705SXin Li// PR8742
94*67e74705SXin Li@interface Test4  {}
95*67e74705SXin Li@property float f;
96*67e74705SXin Li@end
97*67e74705SXin Li// CHECK-LABEL: define void @test4
98*67e74705SXin Livoid test4(Test4 *t) {
99*67e74705SXin Li  extern int test4_printf(const char *, ...);
100*67e74705SXin Li  // CHECK: [[TMP:%.*]] = call float {{.*}} @objc_msgSend
101*67e74705SXin Li  // CHECK-NEXT: [[EXT:%.*]] = fpext float [[TMP]] to double
102*67e74705SXin Li  // CHECK-NEXT: call i32 (i8*, ...) @test4_printf(i8* {{.*}}, double [[EXT]])
103*67e74705SXin Li  // CHECK-NEXT: ret void
104*67e74705SXin Li  test4_printf("%.2f", t.f);
105*67e74705SXin Li}
106*67e74705SXin Li
107*67e74705SXin Li@interface Test5 {
108*67e74705SXin Li  unsigned _x : 5;
109*67e74705SXin Li}
110*67e74705SXin Li@property unsigned x;
111*67e74705SXin Li@end
112*67e74705SXin Li@implementation Test5
113*67e74705SXin Li@synthesize x = _x;
114*67e74705SXin Li@end
115*67e74705SXin Li
116*67e74705SXin Li// rdar://problem/10410531
117*67e74705SXin Li@interface Test6
118*67e74705SXin Li@property void (*prop)(void);
119*67e74705SXin Li@end
120*67e74705SXin Li
121*67e74705SXin Livoid test6_func(void);
122*67e74705SXin Livoid test6(Test6 *a) {
123*67e74705SXin Li  a.prop = test6_func;
124*67e74705SXin Li}
125*67e74705SXin Li
126*67e74705SXin Li// rdar://problem/10507455
127*67e74705SXin Li@interface Test7
128*67e74705SXin Li@property unsigned char x;
129*67e74705SXin Li@end
130*67e74705SXin Livoid test7(Test7 *t) {
131*67e74705SXin Li  t.x &= 2;
132*67e74705SXin Li  t.x |= 5;
133*67e74705SXin Li  t.x ^= 8;
134*67e74705SXin Li}
135*67e74705SXin Li// CHECK:    define void @test7([[TEST7:%.*]]*
136*67e74705SXin Li// CHECK:      [[T:%.*]] = alloca [[TEST7]]*,
137*67e74705SXin Li// CHECK-NEXT: store
138*67e74705SXin Li// CHECK-NEXT: [[T0:%.*]] = load [[TEST7]]*, [[TEST7]]** [[T]], align
139*67e74705SXin Li// CHECK-NEXT: load i8*, i8** @OBJC_SELECTOR_REFERENCES
140*67e74705SXin Li// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST7]]* [[T0]] to i8*
141*67e74705SXin Li// CHECK-NEXT: [[T2:%.*]] = call zeroext i8 bitcast
142*67e74705SXin Li// CHECK-NEXT: [[T3:%.*]] = zext i8 [[T2]] to i32
143*67e74705SXin Li// CHECK-NEXT: [[T4:%.*]] = and i32 [[T3]], 2
144*67e74705SXin Li// CHECK-NEXT: [[T5:%.*]] = trunc i32 [[T4]] to i8
145*67e74705SXin Li// CHECK-NEXT: load i8*, i8** @OBJC_SELECTOR_REFERENCES
146*67e74705SXin Li// CHECK-NEXT: [[T6:%.*]] = bitcast [[TEST7]]* [[T0]] to i8*
147*67e74705SXin Li// CHECK-NEXT: call void bitcast
148*67e74705SXin Li// CHECK-NEXT: [[T0:%.*]] = load [[TEST7]]*, [[TEST7]]** [[T]], align
149*67e74705SXin Li// CHECK-NEXT: load i8*, i8** @OBJC_SELECTOR_REFERENCES
150*67e74705SXin Li// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST7]]* [[T0]] to i8*
151*67e74705SXin Li// CHECK-NEXT: [[T2:%.*]] = call zeroext i8 bitcast
152*67e74705SXin Li// CHECK-NEXT: [[T3:%.*]] = zext i8 [[T2]] to i32
153*67e74705SXin Li// CHECK-NEXT: [[T4:%.*]] = or i32 [[T3]], 5
154*67e74705SXin Li// CHECK-NEXT: [[T5:%.*]] = trunc i32 [[T4]] to i8
155*67e74705SXin Li// CHECK-NEXT: load i8*, i8** @OBJC_SELECTOR_REFERENCES
156*67e74705SXin Li// CHECK-NEXT: [[T6:%.*]] = bitcast [[TEST7]]* [[T0]] to i8*
157*67e74705SXin Li// CHECK-NEXT: call void bitcast
158*67e74705SXin Li// CHECK-NEXT: [[T0:%.*]] = load [[TEST7]]*, [[TEST7]]** [[T]], align
159*67e74705SXin Li// CHECK-NEXT: load i8*, i8** @OBJC_SELECTOR_REFERENCES
160*67e74705SXin Li// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST7]]* [[T0]] to i8*
161*67e74705SXin Li// CHECK-NEXT: [[T2:%.*]] = call zeroext i8 bitcast
162*67e74705SXin Li// CHECK-NEXT: [[T3:%.*]] = zext i8 [[T2]] to i32
163*67e74705SXin Li// CHECK-NEXT: [[T4:%.*]] = xor i32 [[T3]], 8
164*67e74705SXin Li// CHECK-NEXT: [[T5:%.*]] = trunc i32 [[T4]] to i8
165*67e74705SXin Li// CHECK-NEXT: load i8*, i8** @OBJC_SELECTOR_REFERENCES
166*67e74705SXin Li// CHECK-NEXT: [[T6:%.*]] = bitcast [[TEST7]]* [[T0]] to i8*
167*67e74705SXin Li// CHECK-NEXT: call void bitcast
168*67e74705SXin Li// CHECK-NEXT: ret void
169