• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// RUN: %clang_cc1 -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: define void @test2
58A *test2_helper(void);
59void test2() {
60  // CHECK:      [[BASE:%.*]] = call [[A:%.*]]* @test2_helper()
61  // CHECK-NEXT: [[SEL:%.*]] = load 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**
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**
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**
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: 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