1// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm %s -o - | 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  // CHECK-NOT:   __strcpy_chk
59  // 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))
60  strcpy((++i, gbuf), "Hi there");
61}
62
63// CHECK: define void @test8
64void test8() {
65  char *buf[50];
66  // CHECK-NOT:   __strcpy_chk
67  // CHECK:       = call i8* @__inline_strcpy_chk(i8* %{{.*}}, i8* getelementptr inbounds ([9 x i8]* @.str, i32 0, i32 0))
68  strcpy(buf[++gi], "Hi there");
69}
70
71// CHECK: define void @test9
72void test9() {
73  // CHECK-NOT:   __strcpy_chk
74  // CHECK:       = call i8* @__inline_strcpy_chk(i8* %{{.*}}, i8* getelementptr inbounds ([9 x i8]* @.str, i32 0, i32 0))
75  strcpy((char *)((++gi) + gj), "Hi there");
76}
77
78// CHECK: define void @test10
79char **p;
80void test10() {
81  // CHECK-NOT:   __strcpy_chk
82  // CHECK:       = call i8* @__inline_strcpy_chk(i8* %{{.*}}, i8* getelementptr inbounds ([9 x i8]* @.str, i32 0, i32 0))
83  strcpy(*(++p), "Hi there");
84}
85
86// CHECK: define void @test11
87void test11() {
88  // CHECK-NOT:   __strcpy_chk
89  // 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))
90  strcpy(gp = gbuf, "Hi there");
91}
92
93// CHECK: define void @test12
94void test12() {
95  // CHECK-NOT:   __strcpy_chk
96  // CHECK:       = call i8* @__inline_strcpy_chk(i8* %{{.*}}, i8* getelementptr inbounds ([9 x i8]* @.str, i32 0, i32 0))
97  strcpy(++gp, "Hi there");
98}
99
100// CHECK: define void @test13
101void test13() {
102  // CHECK-NOT:   __strcpy_chk
103  // CHECK:       = call i8* @__inline_strcpy_chk(i8* %{{.*}}, i8* getelementptr inbounds ([9 x i8]* @.str, i32 0, i32 0))
104  strcpy(gp++, "Hi there");
105}
106
107// CHECK: define void @test14
108void test14() {
109  // CHECK-NOT:   __strcpy_chk
110  // CHECK:       = call i8* @__inline_strcpy_chk(i8* %{{.*}}, i8* getelementptr inbounds ([9 x i8]* @.str, i32 0, i32 0))
111  strcpy(--gp, "Hi there");
112}
113
114// CHECK: define void @test15
115void test15() {
116  // CHECK-NOT:   __strcpy_chk
117  // CHECK:       = call i8* @__inline_strcpy_chk(i8* %{{..*}}, i8* getelementptr inbounds ([9 x i8]* @.str, i32 0, i32 0))
118  strcpy(gp--, "Hi there");
119}
120
121// CHECK: define void @test16
122void test16() {
123  // CHECK-NOT:   __strcpy_chk
124  // CHECK:       = call i8* @__inline_strcpy_chk(i8* %{{.*}}, i8* getelementptr inbounds ([9 x i8]* @.str, i32 0, i32 0))
125  strcpy(gp += 1, "Hi there");
126}
127
128void test17() {
129  // CHECK: store i32 -1
130  gi = __builtin_object_size(gp++, 0);
131  // CHECK: store i32 -1
132  gi = __builtin_object_size(gp++, 1);
133  // CHECK: store i32 0
134  gi = __builtin_object_size(gp++, 2);
135  // CHECK: store i32 0
136  gi = __builtin_object_size(gp++, 3);
137}
138