Home | History | Annotate | Download | only in CodeGenObjC
      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**
     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**
     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**
     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**
     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]]** [[T]], align
    139 // CHECK-NEXT: load i8** @"\01L_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** @"\01L_OBJC_SELECTOR_REFERENCES
    146 // CHECK-NEXT: [[T6:%.*]] = bitcast [[TEST7]]* [[T0]] to i8*
    147 // CHECK-NEXT: call void bitcast
    148 // CHECK-NEXT: [[T0:%.*]] = load [[TEST7]]** [[T]], align
    149 // CHECK-NEXT: load i8** @"\01L_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** @"\01L_OBJC_SELECTOR_REFERENCES
    156 // CHECK-NEXT: [[T6:%.*]] = bitcast [[TEST7]]* [[T0]] to i8*
    157 // CHECK-NEXT: call void bitcast
    158 // CHECK-NEXT: [[T0:%.*]] = load [[TEST7]]** [[T]], align
    159 // CHECK-NEXT: load i8** @"\01L_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** @"\01L_OBJC_SELECTOR_REFERENCES
    166 // CHECK-NEXT: [[T6:%.*]] = bitcast [[TEST7]]* [[T0]] to i8*
    167 // CHECK-NEXT: call void bitcast
    168 // CHECK-NEXT: ret void
    169