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