1 // RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm -o - %s | FileCheck %s
3 // TODO: actually test most of this instead of just emitting it
5 int printf(const char *, ...);
15 id ob0, ob1, ob2, ob3, ob4;
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;
41 -(void) setZ: (int) arg {
50 @implementation A (Cat)
56 // Test that compound operations only compute the base once.
57 // CHECK-LABEL: define{{.*}} void @test2
58 A *test2_helper(void);
60 // CHECK: [[BASE:%.*]] = call ptr @test2_helper()
61 // CHECK-NEXT: [[SEL:%.*]] = load ptr, ptr
62 // CHECK-NEXT: [[LD:%.*]] = call i32 @objc_msgSend(ptr noundef [[BASE]], ptr noundef [[SEL]])
63 // CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[LD]], 1
64 // CHECK-NEXT: [[SEL:%.*]] = load ptr, ptr
65 // CHECK-NEXT: call void @objc_msgSend(ptr noundef [[BASE]], ptr noundef [[SEL]], i32 noundef [[ADD]])
68 // CHECK: [[BASE:%.*]] = call ptr @test2_helper()
69 // CHECK-NEXT: [[SEL:%.*]] = load ptr, ptr
70 // CHECK-NEXT: [[LD:%.*]] = call i32 @objc_msgSend(ptr noundef [[BASE]], ptr noundef [[SEL]])
71 // CHECK-NEXT: [[ADD:%.*]] = mul nsw i32 [[LD]], 10
72 // CHECK-NEXT: [[SEL:%.*]] = load ptr, ptr
73 // CHECK-NEXT: call void @objc_msgSend(ptr noundef [[BASE]], ptr noundef [[SEL]], i32 noundef [[ADD]])
74 test2_helper().dyn *= 10;
77 // Test aggregate initialization from property reads.
78 // Not crashing is good enough for the property-specific test.
79 struct test3_struct { int x,y,z; };
80 struct test3_nested { struct test3_struct t; };
81 @interface test3_object
82 @property struct test3_struct s;
84 void test3(test3_object *p) {
85 struct test3_struct array[1] = { p.s };
86 struct test3_nested agg = { p.s };
93 // CHECK-LABEL: define{{.*}} void @test4
94 void test4(Test4 *t) {
95 extern int test4_printf(const char *, ...);
96 // CHECK: [[TMP:%.*]] = call float @objc_msgSend
97 // CHECK-NEXT: [[EXT:%.*]] = fpext float [[TMP]] to double
98 // CHECK-NEXT: call i32 (ptr, ...) @test4_printf(ptr {{.*}}, double noundef [[EXT]])
99 // CHECK-NEXT: ret void
100 test4_printf("%.2f", t.f);
106 @property unsigned x;
108 @implementation Test5
113 @property void (*prop)(void);
116 void test6_func(void);
117 void test6(Test6 *a) {
122 @property unsigned char x;
124 void test7(Test7 *t) {
129 // CHECK: define{{.*}} void @test7(ptr
130 // CHECK: [[T:%.*]] = alloca ptr,
132 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[T]], align
133 // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES
134 // CHECK-NEXT: [[T2:%.*]] = call zeroext i8
135 // CHECK-NEXT: [[T3:%.*]] = zext i8 [[T2]] to i32
136 // CHECK-NEXT: [[T4:%.*]] = and i32 [[T3]], 2
137 // CHECK-NEXT: [[T5:%.*]] = trunc i32 [[T4]] to i8
138 // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES
139 // CHECK-NEXT: call void
140 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[T]], align
141 // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES
142 // CHECK-NEXT: [[T2:%.*]] = call zeroext i8
143 // CHECK-NEXT: [[T3:%.*]] = zext i8 [[T2]] to i32
144 // CHECK-NEXT: [[T4:%.*]] = or i32 [[T3]], 5
145 // CHECK-NEXT: [[T5:%.*]] = trunc i32 [[T4]] to i8
146 // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES
147 // CHECK-NEXT: call void
148 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[T]], align
149 // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES
150 // CHECK-NEXT: [[T2:%.*]] = call zeroext i8
151 // CHECK-NEXT: [[T3:%.*]] = zext i8 [[T2]] to i32
152 // CHECK-NEXT: [[T4:%.*]] = xor i32 [[T3]], 8
153 // CHECK-NEXT: [[T5:%.*]] = trunc i32 [[T4]] to i8
154 // CHECK-NEXT: load ptr, ptr @OBJC_SELECTOR_REFERENCES
155 // CHECK-NEXT: call void
156 // CHECK-NEXT: ret void