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 5 int 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 58 A *test2_helper(void); 59 void 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. 83 struct test3_struct { int x,y,z; }; 84 struct test3_nested { struct test3_struct t; }; 85 @interface test3_object 86 @property struct test3_struct s; 87 @end 88 void 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 98 void 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 121 void test6_func(void); 122 void test6(Test6 *a) { 123 a.prop = test6_func; 124 } 125 126 // rdar://problem/10507455 127 @interface Test7 128 @property unsigned char x; 129 @end 130 void 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