| // RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm -o - %s | FileCheck %s | 
 |  | 
 | // TODO: actually test most of this instead of just emitting it | 
 |  | 
 | int printf(const char *, ...); | 
 |  | 
 | @interface Root | 
 | -(id) alloc; | 
 | -(id) init; | 
 | @end | 
 |  | 
 | @interface A : Root { | 
 |   int x; | 
 |   int y, ro, z; | 
 |   id ob0, ob1, ob2, ob3, ob4; | 
 | } | 
 | @property int x; | 
 | @property int y; | 
 | @property int z; | 
 | @property(readonly) int ro; | 
 | @property(assign) id ob0; | 
 | @property(retain) id ob1; | 
 | @property(copy) id ob2; | 
 | @property(retain, nonatomic) id ob3; | 
 | @property(copy, nonatomic) id ob4; | 
 | @end | 
 |  | 
 | @implementation A | 
 | @dynamic x; | 
 | @synthesize y; | 
 | @synthesize z = z; | 
 | @synthesize ro; | 
 | @synthesize ob0; | 
 | @synthesize ob1; | 
 | @synthesize ob2; | 
 | @synthesize ob3; | 
 | @synthesize ob4; | 
 | -(int) y { | 
 |   return x + 1; | 
 | } | 
 | -(void) setZ: (int) arg { | 
 |   x = arg - 1; | 
 | } | 
 | @end | 
 |  | 
 | @interface A (Cat) | 
 | @property int dyn; | 
 | @end | 
 |  | 
 | @implementation A (Cat) | 
 | -(int) dyn { | 
 |   return 10; | 
 | } | 
 | @end | 
 |  | 
 | // Test that compound operations only compute the base once. | 
 | // CHECK-LABEL: define void @test2 | 
 | A *test2_helper(void); | 
 | void test2() { | 
 |   // CHECK:      [[BASE:%.*]] = call [[A:%.*]]* @test2_helper() | 
 |   // CHECK-NEXT: [[SEL:%.*]] = load i8*, i8** | 
 |   // CHECK-NEXT: [[BASETMP:%.*]] = bitcast [[A]]* [[BASE]] to i8* | 
 |   // CHECK-NEXT: [[LD:%.*]] = call i32 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i32 (i8*, i8*)*)(i8* [[BASETMP]], i8* [[SEL]]) | 
 |   // CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[LD]], 1 | 
 |   // CHECK-NEXT: [[SEL:%.*]] = load i8*, i8** | 
 |   // CHECK-NEXT: [[BASETMP:%.*]] = bitcast [[A]]* [[BASE]] to i8* | 
 |   // CHECK-NEXT: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i32)*)(i8* [[BASETMP]], i8* [[SEL]], i32 [[ADD]]) | 
 |   test2_helper().dyn++; | 
 |  | 
 |   // CHECK:      [[BASE:%.*]] = call [[A]]* @test2_helper() | 
 |   // CHECK-NEXT: [[SEL:%.*]] = load i8*, i8** | 
 |   // CHECK-NEXT: [[BASETMP:%.*]] = bitcast [[A]]* [[BASE]] to i8* | 
 |   // CHECK-NEXT: [[LD:%.*]] = call i32 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i32 (i8*, i8*)*)(i8* [[BASETMP]], i8* [[SEL]]) | 
 |   // CHECK-NEXT: [[ADD:%.*]] = mul nsw i32 [[LD]], 10 | 
 |   // CHECK-NEXT: [[SEL:%.*]] = load i8*, i8** | 
 |   // CHECK-NEXT: [[BASETMP:%.*]] = bitcast [[A]]* [[BASE]] to i8* | 
 |   // CHECK-NEXT: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i32)*)(i8* [[BASETMP]], i8* [[SEL]], i32 [[ADD]]) | 
 |   test2_helper().dyn *= 10; | 
 | } | 
 |  | 
 | // Test aggregate initialization from property reads. | 
 | // Not crashing is good enough for the property-specific test. | 
 | struct test3_struct { int x,y,z; }; | 
 | struct test3_nested { struct test3_struct t; }; | 
 | @interface test3_object | 
 | @property struct test3_struct s; | 
 | @end | 
 | void test3(test3_object *p) { | 
 |   struct test3_struct array[1] = { p.s }; | 
 |   struct test3_nested agg = { p.s }; | 
 | } | 
 |  | 
 | // PR8742 | 
 | @interface Test4  {} | 
 | @property float f; | 
 | @end | 
 | // CHECK-LABEL: define void @test4 | 
 | void test4(Test4 *t) { | 
 |   extern int test4_printf(const char *, ...); | 
 |   // CHECK: [[TMP:%.*]] = call float {{.*}} @objc_msgSend | 
 |   // CHECK-NEXT: [[EXT:%.*]] = fpext float [[TMP]] to double | 
 |   // CHECK-NEXT: call i32 (i8*, ...) @test4_printf(i8* {{.*}}, double [[EXT]]) | 
 |   // CHECK-NEXT: ret void | 
 |   test4_printf("%.2f", t.f); | 
 | } | 
 |  | 
 | @interface Test5 { | 
 |   unsigned _x : 5; | 
 | } | 
 | @property unsigned x; | 
 | @end | 
 | @implementation Test5 | 
 | @synthesize x = _x; | 
 | @end | 
 |  | 
 | // rdar://problem/10410531 | 
 | @interface Test6 | 
 | @property void (*prop)(void); | 
 | @end | 
 |  | 
 | void test6_func(void); | 
 | void test6(Test6 *a) { | 
 |   a.prop = test6_func; | 
 | } | 
 |  | 
 | // rdar://problem/10507455 | 
 | @interface Test7 | 
 | @property unsigned char x; | 
 | @end | 
 | void test7(Test7 *t) { | 
 |   t.x &= 2; | 
 |   t.x |= 5; | 
 |   t.x ^= 8; | 
 | } | 
 | // CHECK:    define void @test7([[TEST7:%.*]]* | 
 | // CHECK:      [[T:%.*]] = alloca [[TEST7]]*, | 
 | // CHECK-NEXT: store | 
 | // CHECK-NEXT: [[T0:%.*]] = load [[TEST7]]*, [[TEST7]]** [[T]], align | 
 | // CHECK-NEXT: load i8*, i8** @OBJC_SELECTOR_REFERENCES | 
 | // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST7]]* [[T0]] to i8* | 
 | // CHECK-NEXT: [[T2:%.*]] = call zeroext i8 bitcast | 
 | // CHECK-NEXT: [[T3:%.*]] = zext i8 [[T2]] to i32 | 
 | // CHECK-NEXT: [[T4:%.*]] = and i32 [[T3]], 2 | 
 | // CHECK-NEXT: [[T5:%.*]] = trunc i32 [[T4]] to i8 | 
 | // CHECK-NEXT: load i8*, i8** @OBJC_SELECTOR_REFERENCES | 
 | // CHECK-NEXT: [[T6:%.*]] = bitcast [[TEST7]]* [[T0]] to i8* | 
 | // CHECK-NEXT: call void bitcast | 
 | // CHECK-NEXT: [[T0:%.*]] = load [[TEST7]]*, [[TEST7]]** [[T]], align | 
 | // CHECK-NEXT: load i8*, i8** @OBJC_SELECTOR_REFERENCES | 
 | // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST7]]* [[T0]] to i8* | 
 | // CHECK-NEXT: [[T2:%.*]] = call zeroext i8 bitcast | 
 | // CHECK-NEXT: [[T3:%.*]] = zext i8 [[T2]] to i32 | 
 | // CHECK-NEXT: [[T4:%.*]] = or i32 [[T3]], 5 | 
 | // CHECK-NEXT: [[T5:%.*]] = trunc i32 [[T4]] to i8 | 
 | // CHECK-NEXT: load i8*, i8** @OBJC_SELECTOR_REFERENCES | 
 | // CHECK-NEXT: [[T6:%.*]] = bitcast [[TEST7]]* [[T0]] to i8* | 
 | // CHECK-NEXT: call void bitcast | 
 | // CHECK-NEXT: [[T0:%.*]] = load [[TEST7]]*, [[TEST7]]** [[T]], align | 
 | // CHECK-NEXT: load i8*, i8** @OBJC_SELECTOR_REFERENCES | 
 | // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST7]]* [[T0]] to i8* | 
 | // CHECK-NEXT: [[T2:%.*]] = call zeroext i8 bitcast | 
 | // CHECK-NEXT: [[T3:%.*]] = zext i8 [[T2]] to i32 | 
 | // CHECK-NEXT: [[T4:%.*]] = xor i32 [[T3]], 8 | 
 | // CHECK-NEXT: [[T5:%.*]] = trunc i32 [[T4]] to i8 | 
 | // CHECK-NEXT: load i8*, i8** @OBJC_SELECTOR_REFERENCES | 
 | // CHECK-NEXT: [[T6:%.*]] = bitcast [[TEST7]]* [[T0]] to i8* | 
 | // CHECK-NEXT: call void bitcast | 
 | // CHECK-NEXT: ret void |