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 8static char *__inline_strcpy_chk (char *dest, const char *src) { 9 return __builtin___strcpy_chk(dest, src, __builtin_object_size(dest, 1)); 10} 11 12char gbuf[63]; 13char *gp; 14int gi, gj; 15 16// CHECK: define void @test1 17void 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 23void 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 29void 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 35void 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 41void 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 48void 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 56void 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 66void 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 74void 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 81char **p; 82void 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 89void 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 96void 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 103void 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 110void 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 117void 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 124void 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 131void 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 143unsigned 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