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