Home | History | Annotate | Download | only in CodeGen
      1 // RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -O0 %s -o - 2>&1 | FileCheck %s
      2 
      3 typedef unsigned long size_t;
      4 
      5 struct Foo {
      6   int t[10];
      7 };
      8 
      9 #define PS(N) __attribute__((pass_object_size(N)))
     10 
     11 int gi = 0;
     12 
     13 // CHECK-LABEL: define i32 @ObjectSize0(i8* %{{.*}}, i64)
     14 int ObjectSize0(void *const p PS(0)) {
     15   // CHECK-NOT: @llvm.objectsize
     16   return __builtin_object_size(p, 0);
     17 }
     18 
     19 // CHECK-LABEL: define i32 @ObjectSize1(i8* %{{.*}}, i64)
     20 int ObjectSize1(void *const p PS(1)) {
     21   // CHECK-NOT: @llvm.objectsize
     22   return __builtin_object_size(p, 1);
     23 }
     24 
     25 // CHECK-LABEL: define i32 @ObjectSize2(i8* %{{.*}}, i64)
     26 int ObjectSize2(void *const p PS(2)) {
     27   // CHECK-NOT: @llvm.objectsize
     28   return __builtin_object_size(p, 2);
     29 }
     30 
     31 // CHECK-LABEL: define i32 @ObjectSize3(i8* %{{.*}}, i64)
     32 int ObjectSize3(void *const p PS(3)) {
     33   // CHECK-NOT: @llvm.objectsize
     34   return __builtin_object_size(p, 3);
     35 }
     36 
     37 // CHECK-LABEL: define void @test1
     38 void test1() {
     39   struct Foo t[10];
     40 
     41   // CHECK: call i32 @ObjectSize0(i8* %{{.*}}, i64 360)
     42   gi = ObjectSize0(&t[1]);
     43   // CHECK: call i32 @ObjectSize1(i8* %{{.*}}, i64 360)
     44   gi = ObjectSize1(&t[1]);
     45   // CHECK: call i32 @ObjectSize2(i8* %{{.*}}, i64 360)
     46   gi = ObjectSize2(&t[1]);
     47   // CHECK: call i32 @ObjectSize3(i8* %{{.*}}, i64 360)
     48   gi = ObjectSize3(&t[1]);
     49 
     50   // CHECK: call i32 @ObjectSize0(i8* %{{.*}}, i64 356)
     51   gi = ObjectSize0(&t[1].t[1]);
     52   // CHECK: call i32 @ObjectSize1(i8* %{{.*}}, i64 36)
     53   gi = ObjectSize1(&t[1].t[1]);
     54   // CHECK: call i32 @ObjectSize2(i8* %{{.*}}, i64 356)
     55   gi = ObjectSize2(&t[1].t[1]);
     56   // CHECK: call i32 @ObjectSize3(i8* %{{.*}}, i64 36)
     57   gi = ObjectSize3(&t[1].t[1]);
     58 }
     59 
     60 // CHECK-LABEL: define void @test2
     61 void test2(struct Foo *t) {
     62   // CHECK: call i32 @ObjectSize1(i8* %{{.*}}, i64 36)
     63   gi = ObjectSize1(&t->t[1]);
     64   // CHECK: call i32 @ObjectSize3(i8* %{{.*}}, i64 36)
     65   gi = ObjectSize3(&t->t[1]);
     66 }
     67 
     68 // CHECK-LABEL: define i32 @_Z27NoViableOverloadObjectSize0Pv
     69 int NoViableOverloadObjectSize0(void *const p) __attribute__((overloadable)) {
     70   // CHECK: @llvm.objectsize
     71   return __builtin_object_size(p, 0);
     72 }
     73 
     74 // CHECK-LABEL: define i32 @_Z27NoViableOverloadObjectSize1Pv
     75 int NoViableOverloadObjectSize1(void *const p) __attribute__((overloadable)) {
     76   // CHECK: @llvm.objectsize
     77   return __builtin_object_size(p, 1);
     78 }
     79 
     80 // CHECK-LABEL: define i32 @_Z27NoViableOverloadObjectSize2Pv
     81 int NoViableOverloadObjectSize2(void *const p) __attribute__((overloadable)) {
     82   // CHECK: @llvm.objectsize
     83   return __builtin_object_size(p, 2);
     84 }
     85 
     86 // CHECK-LABEL: define i32 @_Z27NoViableOverloadObjectSize3Pv
     87 int NoViableOverloadObjectSize3(void *const p) __attribute__((overloadable)) {
     88   // CHECK-NOT: @llvm.objectsize
     89   return __builtin_object_size(p, 3);
     90 }
     91 
     92 // CHECK-LABEL: define i32 @_Z27NoViableOverloadObjectSize0Pv
     93 // CHECK-NOT: @llvm.objectsize
     94 int NoViableOverloadObjectSize0(void *const p PS(0))
     95     __attribute__((overloadable)) {
     96   return __builtin_object_size(p, 0);
     97 }
     98 
     99 int NoViableOverloadObjectSize1(void *const p PS(1))
    100     __attribute__((overloadable)) {
    101   return __builtin_object_size(p, 1);
    102 }
    103 
    104 int NoViableOverloadObjectSize2(void *const p PS(2))
    105     __attribute__((overloadable)) {
    106   return __builtin_object_size(p, 2);
    107 }
    108 
    109 int NoViableOverloadObjectSize3(void *const p PS(3))
    110     __attribute__((overloadable)) {
    111   return __builtin_object_size(p, 3);
    112 }
    113 
    114 const static int SHOULDNT_BE_CALLED = -100;
    115 int NoViableOverloadObjectSize0(void *const p PS(0))
    116     __attribute__((overloadable, enable_if(p == 0, "never selected"))) {
    117   return SHOULDNT_BE_CALLED;
    118 }
    119 
    120 int NoViableOverloadObjectSize1(void *const p PS(1))
    121     __attribute__((overloadable, enable_if(p == 0, "never selected"))) {
    122   return SHOULDNT_BE_CALLED;
    123 }
    124 
    125 int NoViableOverloadObjectSize2(void *const p PS(2))
    126     __attribute__((overloadable, enable_if(p == 0, "never selected"))) {
    127   return SHOULDNT_BE_CALLED;
    128 }
    129 
    130 int NoViableOverloadObjectSize3(void *const p PS(3))
    131     __attribute__((overloadable, enable_if(p == 0, "never selected"))) {
    132   return SHOULDNT_BE_CALLED;
    133 }
    134 
    135 // CHECK-LABEL: define void @test3
    136 void test3() {
    137   struct Foo t[10];
    138 
    139   // CHECK: call i32 @_Z27NoViableOverloadObjectSize0PvU17pass_object_size0(i8* %{{.*}}, i64 360)
    140   gi = NoViableOverloadObjectSize0(&t[1]);
    141   // CHECK: call i32 @_Z27NoViableOverloadObjectSize1PvU17pass_object_size1(i8* %{{.*}}, i64 360)
    142   gi = NoViableOverloadObjectSize1(&t[1]);
    143   // CHECK: call i32 @_Z27NoViableOverloadObjectSize2PvU17pass_object_size2(i8* %{{.*}}, i64 360)
    144   gi = NoViableOverloadObjectSize2(&t[1]);
    145   // CHECK: call i32 @_Z27NoViableOverloadObjectSize3PvU17pass_object_size3(i8* %{{.*}}, i64 360)
    146   gi = NoViableOverloadObjectSize3(&t[1]);
    147 
    148   // CHECK: call i32 @_Z27NoViableOverloadObjectSize0PvU17pass_object_size0(i8* %{{.*}}, i64 356)
    149   gi = NoViableOverloadObjectSize0(&t[1].t[1]);
    150   // CHECK: call i32 @_Z27NoViableOverloadObjectSize1PvU17pass_object_size1(i8* %{{.*}}, i64 36)
    151   gi = NoViableOverloadObjectSize1(&t[1].t[1]);
    152   // CHECK: call i32 @_Z27NoViableOverloadObjectSize2PvU17pass_object_size2(i8* %{{.*}}, i64 356)
    153   gi = NoViableOverloadObjectSize2(&t[1].t[1]);
    154   // CHECK: call i32 @_Z27NoViableOverloadObjectSize3PvU17pass_object_size3(i8* %{{.*}}, i64 36)
    155   gi = NoViableOverloadObjectSize3(&t[1].t[1]);
    156 }
    157 
    158 // CHECK-LABEL: define void @test4
    159 void test4(struct Foo *t) {
    160   // CHECK: call i32 @_Z27NoViableOverloadObjectSize0PvU17pass_object_size0(i8* %{{.*}}, i64 %{{.*}})
    161   gi = NoViableOverloadObjectSize0(&t[1]);
    162   // CHECK: call i32 @_Z27NoViableOverloadObjectSize1PvU17pass_object_size1(i8* %{{.*}}, i64 %{{.*}})
    163   gi = NoViableOverloadObjectSize1(&t[1]);
    164   // CHECK: call i32 @_Z27NoViableOverloadObjectSize2PvU17pass_object_size2(i8* %{{.*}}, i64 %{{.*}})
    165   gi = NoViableOverloadObjectSize2(&t[1]);
    166   // CHECK: call i32 @_Z27NoViableOverloadObjectSize3PvU17pass_object_size3(i8* %{{.*}}, i64 0)
    167   gi = NoViableOverloadObjectSize3(&t[1]);
    168 
    169   // CHECK: call i32 @_Z27NoViableOverloadObjectSize0PvU17pass_object_size0(i8* %{{.*}}, i64 %{{.*}})
    170   gi = NoViableOverloadObjectSize0(&t[1].t[1]);
    171   // CHECK: call i32 @_Z27NoViableOverloadObjectSize1PvU17pass_object_size1(i8* %{{.*}}, i64 36)
    172   gi = NoViableOverloadObjectSize1(&t[1].t[1]);
    173   // CHECK: call i32 @_Z27NoViableOverloadObjectSize2PvU17pass_object_size2(i8* %{{.*}}, i64 %{{.*}})
    174   gi = NoViableOverloadObjectSize2(&t[1].t[1]);
    175   // CHECK: call i32 @_Z27NoViableOverloadObjectSize3PvU17pass_object_size3(i8* %{{.*}}, i64 36)
    176   gi = NoViableOverloadObjectSize3(&t[1].t[1]);
    177 }
    178 
    179 void test5() {
    180   struct Foo t[10];
    181 
    182   int (*f)(void *) = &NoViableOverloadObjectSize0;
    183   gi = f(&t[1]);
    184 }
    185 
    186 // CHECK-LABEL: define i32 @IndirectObjectSize0
    187 int IndirectObjectSize0(void *const p PS(0)) {
    188   // CHECK: call i32 @ObjectSize0(i8* %{{.*}}, i64 %{{.*}})
    189   // CHECK-NOT: @llvm.objectsize
    190   return ObjectSize0(p);
    191 }
    192 
    193 // CHECK-LABEL: define i32 @IndirectObjectSize1
    194 int IndirectObjectSize1(void *const p PS(1)) {
    195   // CHECK: call i32 @ObjectSize1(i8* %{{.*}}, i64 %{{.*}})
    196   // CHECK-NOT: @llvm.objectsize
    197   return ObjectSize1(p);
    198 }
    199 
    200 // CHECK-LABEL: define i32 @IndirectObjectSize2
    201 int IndirectObjectSize2(void *const p PS(2)) {
    202   // CHECK: call i32 @ObjectSize2(i8* %{{.*}}, i64 %{{.*}})
    203   // CHECK-NOT: @llvm.objectsize
    204   return ObjectSize2(p);
    205 }
    206 
    207 // CHECK-LABEL: define i32 @IndirectObjectSize3
    208 int IndirectObjectSize3(void *const p PS(3)) {
    209   // CHECK: call i32 @ObjectSize3(i8* %{{.*}}, i64 %{{.*}})
    210   // CHECK-NOT: @llvm.objectsize
    211   return ObjectSize3(p);
    212 }
    213 
    214 int Overload0(void *, size_t, void *, size_t);
    215 int OverloadNoSize(void *, void *);
    216 
    217 int OverloadedObjectSize(void *const p PS(0),
    218                          void *const c PS(0))
    219     __attribute__((overloadable)) __asm__("Overload0");
    220 
    221 int OverloadedObjectSize(void *const p, void *const c)
    222     __attribute__((overloadable)) __asm__("OverloadNoSize");
    223 
    224 // CHECK-LABEL: define void @test6
    225 void test6() {
    226   int known[10], *opaque;
    227 
    228   // CHECK: call i32 @"\01Overload0"
    229   gi = OverloadedObjectSize(&known[0], &known[0]);
    230 
    231   // CHECK: call i32 @"\01Overload0"
    232   gi = OverloadedObjectSize(&known[0], opaque);
    233 
    234   // CHECK: call i32 @"\01Overload0"
    235   gi = OverloadedObjectSize(opaque, &known[0]);
    236 
    237   // CHECK: call i32 @"\01Overload0"
    238   gi = OverloadedObjectSize(opaque, opaque);
    239 }
    240 
    241 int Identity(void *p, size_t i) { return i; }
    242 
    243 // CHECK-NOT: define void @AsmObjectSize
    244 int AsmObjectSize0(void *const p PS(0)) __asm__("Identity");
    245 
    246 int AsmObjectSize1(void *const p PS(1)) __asm__("Identity");
    247 
    248 int AsmObjectSize2(void *const p PS(2)) __asm__("Identity");
    249 
    250 int AsmObjectSize3(void *const p PS(3)) __asm__("Identity");
    251 
    252 // CHECK-LABEL: define void @test7
    253 void test7() {
    254   struct Foo t[10];
    255 
    256   // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 360)
    257   gi = AsmObjectSize0(&t[1]);
    258   // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 360)
    259   gi = AsmObjectSize1(&t[1]);
    260   // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 360)
    261   gi = AsmObjectSize2(&t[1]);
    262   // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 360)
    263   gi = AsmObjectSize3(&t[1]);
    264 
    265   // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 356)
    266   gi = AsmObjectSize0(&t[1].t[1]);
    267   // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 36)
    268   gi = AsmObjectSize1(&t[1].t[1]);
    269   // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 356)
    270   gi = AsmObjectSize2(&t[1].t[1]);
    271   // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 36)
    272   gi = AsmObjectSize3(&t[1].t[1]);
    273 }
    274 
    275 // CHECK-LABEL: define void @test8
    276 void test8(struct Foo *t) {
    277   // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 36)
    278   gi = AsmObjectSize1(&t[1].t[1]);
    279   // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 36)
    280   gi = AsmObjectSize3(&t[1].t[1]);
    281 }
    282 
    283 void DifferingObjectSize0(void *const p __attribute__((pass_object_size(0))));
    284 void DifferingObjectSize1(void *const p __attribute__((pass_object_size(1))));
    285 void DifferingObjectSize2(void *const p __attribute__((pass_object_size(2))));
    286 void DifferingObjectSize3(void *const p __attribute__((pass_object_size(3))));
    287 
    288 // CHECK-LABEL: define void @test9
    289 void test9(void *const p __attribute__((pass_object_size(0)))) {
    290   // CHECK: @llvm.objectsize
    291   DifferingObjectSize2(p);
    292 
    293   // CHECK-NOT: @llvm.objectsize
    294   DifferingObjectSize0(p);
    295   DifferingObjectSize1(p);
    296 
    297   // CHECK: call void @DifferingObjectSize3(i8* %{{.*}}, i64 0)
    298   DifferingObjectSize3(p);
    299 }
    300 
    301 // CHECK-LABEL: define void @test10
    302 void test10(void *const p __attribute__((pass_object_size(1)))) {
    303   // CHECK: @llvm.objectsize
    304   DifferingObjectSize2(p);
    305   // CHECK: @llvm.objectsize
    306   DifferingObjectSize0(p);
    307 
    308   // CHECK-NOT: @llvm.objectsize
    309   DifferingObjectSize1(p);
    310 
    311   // CHECK: call void @DifferingObjectSize3(i8* %{{.*}}, i64 0)
    312   DifferingObjectSize3(p);
    313 }
    314 
    315 // CHECK-LABEL: define void @test11
    316 void test11(void *const p __attribute__((pass_object_size(2)))) {
    317   // CHECK: @llvm.objectsize
    318   DifferingObjectSize0(p);
    319   // CHECK: @llvm.objectsize
    320   DifferingObjectSize1(p);
    321 
    322   // CHECK-NOT: @llvm.objectsize
    323   DifferingObjectSize2(p);
    324 
    325   // CHECK: call void @DifferingObjectSize3(i8* %{{.*}}, i64 0)
    326   DifferingObjectSize3(p);
    327 }
    328 
    329 // CHECK-LABEL: define void @test12
    330 void test12(void *const p __attribute__((pass_object_size(3)))) {
    331   // CHECK: @llvm.objectsize
    332   DifferingObjectSize0(p);
    333   // CHECK: @llvm.objectsize
    334   DifferingObjectSize1(p);
    335 
    336   // CHECK-NOT: @llvm.objectsize
    337   DifferingObjectSize2(p);
    338   DifferingObjectSize3(p);
    339 }
    340 
    341 // CHECK-LABEL: define void @test13
    342 void test13() {
    343   // Ensuring that we don't lower objectsize if the expression has side-effects
    344   char c[10];
    345   char *p = c;
    346 
    347   // CHECK: @llvm.objectsize
    348   ObjectSize0(p);
    349 
    350   // CHECK-NOT: @llvm.objectsize
    351   ObjectSize0(++p);
    352   ObjectSize0(p++);
    353 }
    354 
    355 // There was a bug where variadic functions with pass_object_size would cause
    356 // problems in the form of failed assertions.
    357 void my_sprintf(char *const c __attribute__((pass_object_size(0))), ...) {}
    358 
    359 // CHECK-LABEL: define void @test14
    360 void test14(char *c) {
    361   // CHECK: @llvm.objectsize
    362   // CHECK: call void (i8*, i64, ...) @my_sprintf
    363   my_sprintf(c);
    364 
    365   // CHECK: @llvm.objectsize
    366   // CHECK: call void (i8*, i64, ...) @my_sprintf
    367   my_sprintf(c, 1, 2, 3);
    368 }
    369