1 /* This test needs runtime that provides stpcpy function. */
2 /* { dg-do run { target *-*-linux* *-*-gnu* } } */
3 /* { dg-options "-O2 -fdump-tree-strlen" } */
4
5 #define USE_GNU
6 #include "strlenopt.h"
7
8 __attribute__((noinline, noclone)) int
foo(const char * p)9 foo (const char *p)
10 {
11 static int c;
12 const char *q[] = { "123498765abcde", "123498765..", "129abcde", "129abcde" };
13 if (strcmp (p, q[c]) != 0)
14 abort ();
15 return c++;
16 }
17
18 __attribute__((noinline, noclone)) void
bar(const char * p,const char * q)19 bar (const char *p, const char *q)
20 {
21 size_t l;
22 /* This strlen stays. */
23 char *a = __builtin_alloca (strlen (p) + 50);
24 /* strcpy can be optimized into memcpy. */
25 strcpy (a, p);
26 /* strcat into stpcpy. */
27 strcat (a, q);
28 /* This strlen can be optimized away. */
29 l = strlen (a);
30 /* This becomes memcpy. */
31 strcat (a, "abcde");
32 if (!foo (a))
33 /* And this one too. */
34 strcpy (a + l, "..");
35 foo (a);
36 }
37
38 int
main()39 main ()
40 {
41 const char *volatile s1 = "1234";
42 const char *volatile s2 = "98765";
43 const char *volatile s3 = "12";
44 const char *volatile s4 = "9";
45 bar (s1, s2);
46 bar (s3, s4);
47 return 0;
48 }
49
50 /* { dg-final { scan-tree-dump-times "strlen \\(" 1 "strlen" } } */
51 /* { dg-final { scan-tree-dump-times "memcpy \\(" 3 "strlen" } } */
52 /* { dg-final { scan-tree-dump-times "mempcpy \\(" 0 "strlen" } } */
53 /* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen" } } */
54 /* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */
55 /* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */
56 /* { dg-final { scan-tree-dump-times "stpcpy \\(" 1 "strlen" } } */
57