13573b2c84372d9484296fa658f5276f6c09acb92Daniel Dunbar// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm %s -o - | FileCheck %s
27b83de5e2b28533be349f48552b665a2ea95ddecBenjamin Kramer
37b83de5e2b28533be349f48552b665a2ea95ddecBenjamin Kramer#define strcpy(dest, src) \
47b83de5e2b28533be349f48552b665a2ea95ddecBenjamin Kramer  ((__builtin_object_size(dest, 0) != -1ULL) \
57b83de5e2b28533be349f48552b665a2ea95ddecBenjamin Kramer   ? __builtin___strcpy_chk (dest, src, __builtin_object_size(dest, 1)) \
67b83de5e2b28533be349f48552b665a2ea95ddecBenjamin Kramer   : __inline_strcpy_chk(dest, src))
77b83de5e2b28533be349f48552b665a2ea95ddecBenjamin Kramer
87b83de5e2b28533be349f48552b665a2ea95ddecBenjamin Kramerstatic char *__inline_strcpy_chk (char *dest, const char *src) {
97b83de5e2b28533be349f48552b665a2ea95ddecBenjamin Kramer  return __builtin___strcpy_chk(dest, src, __builtin_object_size(dest, 1));
107b83de5e2b28533be349f48552b665a2ea95ddecBenjamin Kramer}
11d3be5cda6ab48629d28ae9f0609f526dff16eb87Mike Stump
12d3be5cda6ab48629d28ae9f0609f526dff16eb87Mike Stumpchar gbuf[63];
13d3be5cda6ab48629d28ae9f0609f526dff16eb87Mike Stumpchar *gp;
14dcead8e2ce0078f75eda5be5774865a7f4ac0223Mike Stumpint gi, gj;
15d3be5cda6ab48629d28ae9f0609f526dff16eb87Mike Stump
1631bb25d9d5be2d3a68858ce8094cb7e9131bc24cDaniel Dunbar// CHECK: define void @test1
17d3be5cda6ab48629d28ae9f0609f526dff16eb87Mike Stumpvoid test1() {
18954589735392ac96da5ac2af7f1e72f1b80cf187Mike Stump  // 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)
19d3be5cda6ab48629d28ae9f0609f526dff16eb87Mike Stump  strcpy(&gbuf[4], "Hi there");
20d3be5cda6ab48629d28ae9f0609f526dff16eb87Mike Stump}
21d3be5cda6ab48629d28ae9f0609f526dff16eb87Mike Stump
2231bb25d9d5be2d3a68858ce8094cb7e9131bc24cDaniel Dunbar// CHECK: define void @test2
23d3be5cda6ab48629d28ae9f0609f526dff16eb87Mike Stumpvoid test2() {
24954589735392ac96da5ac2af7f1e72f1b80cf187Mike Stump  // 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)
25d3be5cda6ab48629d28ae9f0609f526dff16eb87Mike Stump  strcpy(gbuf, "Hi there");
26d3be5cda6ab48629d28ae9f0609f526dff16eb87Mike Stump}
27d3be5cda6ab48629d28ae9f0609f526dff16eb87Mike Stump
2831bb25d9d5be2d3a68858ce8094cb7e9131bc24cDaniel Dunbar// CHECK: define void @test3
294e930c282a06a088e84e6b34c5bb721ed8fd52c7Mike Stumpvoid test3() {
30954589735392ac96da5ac2af7f1e72f1b80cf187Mike Stump  // 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)
314e930c282a06a088e84e6b34c5bb721ed8fd52c7Mike Stump  strcpy(&gbuf[100], "Hi there");
324e930c282a06a088e84e6b34c5bb721ed8fd52c7Mike Stump}
334e930c282a06a088e84e6b34c5bb721ed8fd52c7Mike Stump
3431bb25d9d5be2d3a68858ce8094cb7e9131bc24cDaniel Dunbar// CHECK: define void @test4
35d3be5cda6ab48629d28ae9f0609f526dff16eb87Mike Stumpvoid test4() {
36954589735392ac96da5ac2af7f1e72f1b80cf187Mike Stump  // 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)
374e930c282a06a088e84e6b34c5bb721ed8fd52c7Mike Stump  strcpy((char*)(void*)&gbuf[-1], "Hi there");
384e930c282a06a088e84e6b34c5bb721ed8fd52c7Mike Stump}
394e930c282a06a088e84e6b34c5bb721ed8fd52c7Mike Stump
4031bb25d9d5be2d3a68858ce8094cb7e9131bc24cDaniel Dunbar// CHECK: define void @test5
414e930c282a06a088e84e6b34c5bb721ed8fd52c7Mike Stumpvoid test5() {
42954589735392ac96da5ac2af7f1e72f1b80cf187Mike Stump  // CHECK:     = load i8** @gp
43954589735392ac96da5ac2af7f1e72f1b80cf187Mike Stump  // CHECK-NEXT:= call i64 @llvm.objectsize.i64(i8* %{{.*}}, i1 false)
444e930c282a06a088e84e6b34c5bb721ed8fd52c7Mike Stump  strcpy(gp, "Hi there");
45d3be5cda6ab48629d28ae9f0609f526dff16eb87Mike Stump}
46d3be5cda6ab48629d28ae9f0609f526dff16eb87Mike Stump
4731bb25d9d5be2d3a68858ce8094cb7e9131bc24cDaniel Dunbar// CHECK: define void @test6
484e930c282a06a088e84e6b34c5bb721ed8fd52c7Mike Stumpvoid test6() {
4907677bbc5b3ebd35868bc3a2a6fd4597373485e0Mike Stump  char buf[57];
5007677bbc5b3ebd35868bc3a2a6fd4597373485e0Mike Stump
51954589735392ac96da5ac2af7f1e72f1b80cf187Mike Stump  // CHECK:       = call i8* @__strcpy_chk(i8* %{{.*}}, i8* getelementptr inbounds ([9 x i8]* @.str, i32 0, i32 0), i64 53)
5207677bbc5b3ebd35868bc3a2a6fd4597373485e0Mike Stump  strcpy(&buf[4], "Hi there");
5307677bbc5b3ebd35868bc3a2a6fd4597373485e0Mike Stump}
54dcead8e2ce0078f75eda5be5774865a7f4ac0223Mike Stump
5531bb25d9d5be2d3a68858ce8094cb7e9131bc24cDaniel Dunbar// CHECK: define void @test7
56dcead8e2ce0078f75eda5be5774865a7f4ac0223Mike Stumpvoid test7() {
57dcead8e2ce0078f75eda5be5774865a7f4ac0223Mike Stump  int i;
587592f30a01a7f53b2dc509eff2bdfd221c16d822Mike Stump  // CHECK-NOT:   __strcpy_chk
59954589735392ac96da5ac2af7f1e72f1b80cf187Mike Stump  // 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))
60dcead8e2ce0078f75eda5be5774865a7f4ac0223Mike Stump  strcpy((++i, gbuf), "Hi there");
61dcead8e2ce0078f75eda5be5774865a7f4ac0223Mike Stump}
62dcead8e2ce0078f75eda5be5774865a7f4ac0223Mike Stump
6331bb25d9d5be2d3a68858ce8094cb7e9131bc24cDaniel Dunbar// CHECK: define void @test8
64dcead8e2ce0078f75eda5be5774865a7f4ac0223Mike Stumpvoid test8() {
65dcead8e2ce0078f75eda5be5774865a7f4ac0223Mike Stump  char *buf[50];
667592f30a01a7f53b2dc509eff2bdfd221c16d822Mike Stump  // CHECK-NOT:   __strcpy_chk
67954589735392ac96da5ac2af7f1e72f1b80cf187Mike Stump  // CHECK:       = call i8* @__inline_strcpy_chk(i8* %{{.*}}, i8* getelementptr inbounds ([9 x i8]* @.str, i32 0, i32 0))
68dcead8e2ce0078f75eda5be5774865a7f4ac0223Mike Stump  strcpy(buf[++gi], "Hi there");
69dcead8e2ce0078f75eda5be5774865a7f4ac0223Mike Stump}
70dcead8e2ce0078f75eda5be5774865a7f4ac0223Mike Stump
7131bb25d9d5be2d3a68858ce8094cb7e9131bc24cDaniel Dunbar// CHECK: define void @test9
72dcead8e2ce0078f75eda5be5774865a7f4ac0223Mike Stumpvoid test9() {
737592f30a01a7f53b2dc509eff2bdfd221c16d822Mike Stump  // CHECK-NOT:   __strcpy_chk
74954589735392ac96da5ac2af7f1e72f1b80cf187Mike Stump  // CHECK:       = call i8* @__inline_strcpy_chk(i8* %{{.*}}, i8* getelementptr inbounds ([9 x i8]* @.str, i32 0, i32 0))
75dcead8e2ce0078f75eda5be5774865a7f4ac0223Mike Stump  strcpy((char *)((++gi) + gj), "Hi there");
76dcead8e2ce0078f75eda5be5774865a7f4ac0223Mike Stump}
77dcead8e2ce0078f75eda5be5774865a7f4ac0223Mike Stump
7831bb25d9d5be2d3a68858ce8094cb7e9131bc24cDaniel Dunbar// CHECK: define void @test10
79dcead8e2ce0078f75eda5be5774865a7f4ac0223Mike Stumpchar **p;
80dcead8e2ce0078f75eda5be5774865a7f4ac0223Mike Stumpvoid test10() {
817592f30a01a7f53b2dc509eff2bdfd221c16d822Mike Stump  // CHECK-NOT:   __strcpy_chk
82954589735392ac96da5ac2af7f1e72f1b80cf187Mike Stump  // CHECK:       = call i8* @__inline_strcpy_chk(i8* %{{.*}}, i8* getelementptr inbounds ([9 x i8]* @.str, i32 0, i32 0))
83dcead8e2ce0078f75eda5be5774865a7f4ac0223Mike Stump  strcpy(*(++p), "Hi there");
84dcead8e2ce0078f75eda5be5774865a7f4ac0223Mike Stump}
85bab3457bcb5fe58a093026002769c9cd68a157ecMike Stump
8631bb25d9d5be2d3a68858ce8094cb7e9131bc24cDaniel Dunbar// CHECK: define void @test11
87bab3457bcb5fe58a093026002769c9cd68a157ecMike Stumpvoid test11() {
887592f30a01a7f53b2dc509eff2bdfd221c16d822Mike Stump  // CHECK-NOT:   __strcpy_chk
8931bb25d9d5be2d3a68858ce8094cb7e9131bc24cDaniel Dunbar  // 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))
90bab3457bcb5fe58a093026002769c9cd68a157ecMike Stump  strcpy(gp = gbuf, "Hi there");
91bab3457bcb5fe58a093026002769c9cd68a157ecMike Stump}
92bab3457bcb5fe58a093026002769c9cd68a157ecMike Stump
9331bb25d9d5be2d3a68858ce8094cb7e9131bc24cDaniel Dunbar// CHECK: define void @test12
94bab3457bcb5fe58a093026002769c9cd68a157ecMike Stumpvoid test12() {
957592f30a01a7f53b2dc509eff2bdfd221c16d822Mike Stump  // CHECK-NOT:   __strcpy_chk
96954589735392ac96da5ac2af7f1e72f1b80cf187Mike Stump  // CHECK:       = call i8* @__inline_strcpy_chk(i8* %{{.*}}, i8* getelementptr inbounds ([9 x i8]* @.str, i32 0, i32 0))
97bab3457bcb5fe58a093026002769c9cd68a157ecMike Stump  strcpy(++gp, "Hi there");
98bab3457bcb5fe58a093026002769c9cd68a157ecMike Stump}
99bab3457bcb5fe58a093026002769c9cd68a157ecMike Stump
10031bb25d9d5be2d3a68858ce8094cb7e9131bc24cDaniel Dunbar// CHECK: define void @test13
101bab3457bcb5fe58a093026002769c9cd68a157ecMike Stumpvoid test13() {
1027592f30a01a7f53b2dc509eff2bdfd221c16d822Mike Stump  // CHECK-NOT:   __strcpy_chk
103954589735392ac96da5ac2af7f1e72f1b80cf187Mike Stump  // CHECK:       = call i8* @__inline_strcpy_chk(i8* %{{.*}}, i8* getelementptr inbounds ([9 x i8]* @.str, i32 0, i32 0))
104bab3457bcb5fe58a093026002769c9cd68a157ecMike Stump  strcpy(gp++, "Hi there");
105bab3457bcb5fe58a093026002769c9cd68a157ecMike Stump}
106bab3457bcb5fe58a093026002769c9cd68a157ecMike Stump
10731bb25d9d5be2d3a68858ce8094cb7e9131bc24cDaniel Dunbar// CHECK: define void @test14
108bab3457bcb5fe58a093026002769c9cd68a157ecMike Stumpvoid test14() {
1097592f30a01a7f53b2dc509eff2bdfd221c16d822Mike Stump  // CHECK-NOT:   __strcpy_chk
110954589735392ac96da5ac2af7f1e72f1b80cf187Mike Stump  // CHECK:       = call i8* @__inline_strcpy_chk(i8* %{{.*}}, i8* getelementptr inbounds ([9 x i8]* @.str, i32 0, i32 0))
111bab3457bcb5fe58a093026002769c9cd68a157ecMike Stump  strcpy(--gp, "Hi there");
112bab3457bcb5fe58a093026002769c9cd68a157ecMike Stump}
113bab3457bcb5fe58a093026002769c9cd68a157ecMike Stump
11431bb25d9d5be2d3a68858ce8094cb7e9131bc24cDaniel Dunbar// CHECK: define void @test15
115bab3457bcb5fe58a093026002769c9cd68a157ecMike Stumpvoid test15() {
1167592f30a01a7f53b2dc509eff2bdfd221c16d822Mike Stump  // CHECK-NOT:   __strcpy_chk
117954589735392ac96da5ac2af7f1e72f1b80cf187Mike Stump  // CHECK:       = call i8* @__inline_strcpy_chk(i8* %{{..*}}, i8* getelementptr inbounds ([9 x i8]* @.str, i32 0, i32 0))
118bab3457bcb5fe58a093026002769c9cd68a157ecMike Stump  strcpy(gp--, "Hi there");
119bab3457bcb5fe58a093026002769c9cd68a157ecMike Stump}
120abe84d3316a002df684a595d9bfa54e9bc3e64fbMike Stump
12131bb25d9d5be2d3a68858ce8094cb7e9131bc24cDaniel Dunbar// CHECK: define void @test16
122abe84d3316a002df684a595d9bfa54e9bc3e64fbMike Stumpvoid test16() {
1237592f30a01a7f53b2dc509eff2bdfd221c16d822Mike Stump  // CHECK-NOT:   __strcpy_chk
124954589735392ac96da5ac2af7f1e72f1b80cf187Mike Stump  // CHECK:       = call i8* @__inline_strcpy_chk(i8* %{{.*}}, i8* getelementptr inbounds ([9 x i8]* @.str, i32 0, i32 0))
125abe84d3316a002df684a595d9bfa54e9bc3e64fbMike Stump  strcpy(gp += 1, "Hi there");
126abe84d3316a002df684a595d9bfa54e9bc3e64fbMike Stump}
12781bcc4ac937f901e9e94754122350ee673dce573Benjamin Kramer
12881bcc4ac937f901e9e94754122350ee673dce573Benjamin Kramervoid test17() {
12981bcc4ac937f901e9e94754122350ee673dce573Benjamin Kramer  // CHECK: store i32 -1
13081bcc4ac937f901e9e94754122350ee673dce573Benjamin Kramer  gi = __builtin_object_size(gp++, 0);
13181bcc4ac937f901e9e94754122350ee673dce573Benjamin Kramer  // CHECK: store i32 -1
13281bcc4ac937f901e9e94754122350ee673dce573Benjamin Kramer  gi = __builtin_object_size(gp++, 1);
13381bcc4ac937f901e9e94754122350ee673dce573Benjamin Kramer  // CHECK: store i32 0
13481bcc4ac937f901e9e94754122350ee673dce573Benjamin Kramer  gi = __builtin_object_size(gp++, 2);
13581bcc4ac937f901e9e94754122350ee673dce573Benjamin Kramer  // CHECK: store i32 0
13681bcc4ac937f901e9e94754122350ee673dce573Benjamin Kramer  gi = __builtin_object_size(gp++, 3);
13781bcc4ac937f901e9e94754122350ee673dce573Benjamin Kramer}
138