1 /* { dg-do run } */
2 /* { dg-options "-O2 -fdump-tree-strlen" } */
3 
4 #include "strlenopt.h"
5 
6 struct S { char *p; size_t l; };
7 
8 __attribute__((noinline, noclone)) struct S
foo(char * x,int n)9 foo (char *x, int n)
10 {
11   int i;
12   char a[64];
13   char *p = strchr (x, '\0');
14   struct S s;
15   /* strcpy here is optimized into memcpy, length computed as p - x + 1.  */
16   strcpy (a, x);
17   /* strcat here is optimized into memcpy.  */
18   strcat (p, "abcd");
19   for (i = 0; i < n; i++)
20     if ((i % 123) == 53)
21       /* strcat here is optimized into strlen and memcpy.  */
22       strcat (a, "efg");
23   s.p = strdup (a);
24   /* The strlen should be optimized here into 4.  */
25   s.l = strlen (p);
26   return s;
27 }
28 
29 int
main()30 main ()
31 {
32   char buf[32];
33   struct S s;
34   buf[0] = 'z';
35   buf[1] = '\0';
36   s = foo (buf, 0);
37   if (s.l != 4 || memcmp (buf, "zabcd", 6) != 0)
38     abort ();
39   if (s.p == NULL)
40     return 0;
41   if (memcmp (s.p, "z", 2) != 0)
42     abort ();
43   s = foo (buf, 60);
44   if (s.l != 4 || memcmp (buf, "zabcdabcd", 10) != 0)
45     abort ();
46   if (s.p == NULL)
47     return 0;
48   if (memcmp (s.p, "zabcdefg", 9) != 0)
49     abort ();
50   s = foo (buf, 240);
51   if (s.l != 4 || memcmp (buf, "zabcdabcdabcd", 14) != 0)
52     abort ();
53   if (s.p == NULL)
54     return 0;
55   if (memcmp (s.p, "zabcdabcdefgefg", 16) != 0)
56     abort ();
57   return 0;
58 }
59 
60 /* { dg-final { scan-tree-dump-times "strlen \\(" 2 "strlen" } } */
61 /* { dg-final { scan-tree-dump-times "memcpy \\(" 3 "strlen" } } */
62 /* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen" } } */
63 /* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */
64 /* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */
65 /* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen" } } */
66