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