Home | History | Annotate | Download | only in CodeGen
      1 // RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm %s -o - 2>&1 | FileCheck %s
      2 
      3 #define strcpy(dest, src) \
      4   ((__builtin_object_size(dest, 0) != -1ULL) \
      5    ? __builtin___strcpy_chk (dest, src, __builtin_object_size(dest, 1)) \
      6    : __inline_strcpy_chk(dest, src))
      7 
      8 static char *__inline_strcpy_chk (char *dest, const char *src) {
      9   return __builtin___strcpy_chk(dest, src, __builtin_object_size(dest, 1));
     10 }
     11 
     12 char gbuf[63];
     13 char *gp;
     14 int gi, gj;
     15 
     16 // CHECK: define void @test1
     17 void test1() {
     18   // CHECK:     = call i8* @__strcpy_chk(i8* getelementptr inbounds ([63 x i8]* @gbuf, i32 0, i64 4), i8* getelementptr inbounds ([9 x i8]* @.str, i32 0, i32 0), i64 59)
     19   strcpy(&gbuf[4], "Hi there");
     20 }
     21 
     22 // CHECK: define void @test2
     23 void test2() {
     24   // CHECK:     = call i8* @__strcpy_chk(i8* getelementptr inbounds ([63 x i8]* @gbuf, i32 0, i32 0), i8* getelementptr inbounds ([9 x i8]* @.str, i32 0, i32 0), i64 63)
     25   strcpy(gbuf, "Hi there");
     26 }
     27 
     28 // CHECK: define void @test3
     29 void test3() {
     30   // CHECK:     = call i8* @__strcpy_chk(i8* getelementptr inbounds ([63 x i8]* @gbuf, i64 1, i64 37), i8* getelementptr inbounds ([9 x i8]* @.str, i32 0, i32 0), i64 0)
     31   strcpy(&gbuf[100], "Hi there");
     32 }
     33 
     34 // CHECK: define void @test4
     35 void test4() {
     36   // CHECK:     = call i8* @__strcpy_chk(i8* getelementptr inbounds ([63 x i8]* @gbuf, i32 0, i64 -1), i8* getelementptr inbounds ([9 x i8]* @.str, i32 0, i32 0), i64 0)
     37   strcpy((char*)(void*)&gbuf[-1], "Hi there");
     38 }
     39 
     40 // CHECK: define void @test5
     41 void test5() {
     42   // CHECK:     = load i8** @gp
     43   // CHECK-NEXT:= call i64 @llvm.objectsize.i64(i8* %{{.*}}, i1 false)
     44   strcpy(gp, "Hi there");
     45 }
     46 
     47 // CHECK: define void @test6
     48 void test6() {
     49   char buf[57];
     50 
     51   // CHECK:       = call i8* @__strcpy_chk(i8* %{{.*}}, i8* getelementptr inbounds ([9 x i8]* @.str, i32 0, i32 0), i64 53)
     52   strcpy(&buf[4], "Hi there");
     53 }
     54 
     55 // CHECK: define void @test7
     56 void test7() {
     57   int i;
     58   // Ensure we only evaluate the side-effect once.
     59   // CHECK:     = add
     60   // CHECK-NOT: = add
     61   // CHECK:     = call i8* @__strcpy_chk(i8* getelementptr inbounds ([63 x i8]* @gbuf, i32 0, i32 0), i8* getelementptr inbounds ([9 x i8]* @.str, i32 0, i32 0), i64 63)
     62   strcpy((++i, gbuf), "Hi there");
     63 }
     64 
     65 // CHECK: define void @test8
     66 void test8() {
     67   char *buf[50];
     68   // CHECK-NOT:   __strcpy_chk
     69   // CHECK:       = call i8* @__inline_strcpy_chk(i8* %{{.*}}, i8* getelementptr inbounds ([9 x i8]* @.str, i32 0, i32 0))
     70   strcpy(buf[++gi], "Hi there");
     71 }
     72 
     73 // CHECK: define void @test9
     74 void test9() {
     75   // CHECK-NOT:   __strcpy_chk
     76   // CHECK:       = call i8* @__inline_strcpy_chk(i8* %{{.*}}, i8* getelementptr inbounds ([9 x i8]* @.str, i32 0, i32 0))
     77   strcpy((char *)((++gi) + gj), "Hi there");
     78 }
     79 
     80 // CHECK: define void @test10
     81 char **p;
     82 void test10() {
     83   // CHECK-NOT:   __strcpy_chk
     84   // CHECK:       = call i8* @__inline_strcpy_chk(i8* %{{.*}}, i8* getelementptr inbounds ([9 x i8]* @.str, i32 0, i32 0))
     85   strcpy(*(++p), "Hi there");
     86 }
     87 
     88 // CHECK: define void @test11
     89 void test11() {
     90   // CHECK-NOT:   __strcpy_chk
     91   // CHECK:       = call i8* @__inline_strcpy_chk(i8* getelementptr inbounds ([63 x i8]* @gbuf, i32 0, i32 0), i8* getelementptr inbounds ([9 x i8]* @.str, i32 0, i32 0))
     92   strcpy(gp = gbuf, "Hi there");
     93 }
     94 
     95 // CHECK: define void @test12
     96 void test12() {
     97   // CHECK-NOT:   __strcpy_chk
     98   // CHECK:       = call i8* @__inline_strcpy_chk(i8* %{{.*}}, i8* getelementptr inbounds ([9 x i8]* @.str, i32 0, i32 0))
     99   strcpy(++gp, "Hi there");
    100 }
    101 
    102 // CHECK: define void @test13
    103 void test13() {
    104   // CHECK-NOT:   __strcpy_chk
    105   // CHECK:       = call i8* @__inline_strcpy_chk(i8* %{{.*}}, i8* getelementptr inbounds ([9 x i8]* @.str, i32 0, i32 0))
    106   strcpy(gp++, "Hi there");
    107 }
    108 
    109 // CHECK: define void @test14
    110 void test14() {
    111   // CHECK-NOT:   __strcpy_chk
    112   // CHECK:       = call i8* @__inline_strcpy_chk(i8* %{{.*}}, i8* getelementptr inbounds ([9 x i8]* @.str, i32 0, i32 0))
    113   strcpy(--gp, "Hi there");
    114 }
    115 
    116 // CHECK: define void @test15
    117 void test15() {
    118   // CHECK-NOT:   __strcpy_chk
    119   // CHECK:       = call i8* @__inline_strcpy_chk(i8* %{{..*}}, i8* getelementptr inbounds ([9 x i8]* @.str, i32 0, i32 0))
    120   strcpy(gp--, "Hi there");
    121 }
    122 
    123 // CHECK: define void @test16
    124 void test16() {
    125   // CHECK-NOT:   __strcpy_chk
    126   // CHECK:       = call i8* @__inline_strcpy_chk(i8* %{{.*}}, i8* getelementptr inbounds ([9 x i8]* @.str, i32 0, i32 0))
    127   strcpy(gp += 1, "Hi there");
    128 }
    129 
    130 // CHECK: @test17
    131 void test17() {
    132   // CHECK: store i32 -1
    133   gi = __builtin_object_size(gp++, 0);
    134   // CHECK: store i32 -1
    135   gi = __builtin_object_size(gp++, 1);
    136   // CHECK: store i32 0
    137   gi = __builtin_object_size(gp++, 2);
    138   // CHECK: store i32 0
    139   gi = __builtin_object_size(gp++, 3);
    140 }
    141 
    142 // CHECK: @test18
    143 unsigned test18(int cond) {
    144   int a[4], b[4];
    145   // CHECK: phi i32*
    146   // CHECK: call i64 @llvm.objectsize.i64
    147   return __builtin_object_size(cond ? a : b, 0);
    148 }
    149