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(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]]) 66 test2_helper().dyn++; 67 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; 75} 76 77// Test aggregate initialization from property reads. 78// Not crashing is good enough for the property-specific test. 79struct test3_struct { int x,y,z; }; 80struct test3_nested { struct test3_struct t; }; 81@interface test3_object 82@property struct test3_struct s; 83@end 84void test3(test3_object *p) { 85 struct test3_struct array[1] = { p.s }; 86 struct test3_nested agg = { p.s }; 87} 88 89// PR8742 90@interface Test4 {} 91@property float f; 92@end 93// CHECK-LABEL: define{{.*}} void @test4 94void 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); 101} 102 103@interface Test5 { 104 unsigned _x : 5; 105} 106@property unsigned x; 107@end 108@implementation Test5 109@synthesize x = _x; 110@end 111 112@interface Test6 113@property void (*prop)(void); 114@end 115 116void test6_func(void); 117void test6(Test6 *a) { 118 a.prop = test6_func; 119} 120 121@interface Test7 122@property unsigned char x; 123@end 124void test7(Test7 *t) { 125 t.x &= 2; 126 t.x |= 5; 127 t.x ^= 8; 128} 129// CHECK: define{{.*}} void @test7(ptr 130// CHECK: [[T:%.*]] = alloca ptr, 131// CHECK-NEXT: store 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 157