1 /* { dg-do run } */
2 /* { dg-options "-O2 -fdump-tree-strlen" } */
3 
4 #include "strlenopt.h"
5 
6 __attribute__((noinline, noclone)) char *
foo(char * p,const char * q)7 foo (char *p, const char *q)
8 {
9   char *e = strchr (p, '\0');
10   strcat (p, q);
11   return e;
12 }
13 
14 __attribute__((noinline, noclone)) char *
bar(char * p)15 bar (char *p)
16 {
17   memcpy (p, "abcd", 5);
18   return strchr (p, '\0');
19 }
20 
21 __attribute__((noinline, noclone)) void
baz(char * p)22 baz (char *p)
23 {
24   char *e = strchr (p, '\0');
25   strcat (e, "abcd");
26 }
27 
28 char buf[64];
29 
30 int
main()31 main ()
32 {
33   char *volatile p = buf;
34   const char *volatile q = "ij";
35   memset (buf, 'v', 3);
36   if (foo (p, q) != buf + 3
37       || memcmp (buf, "vvvij\0\0\0\0", 10) != 0)
38     abort ();
39   memset (buf, '\0', sizeof buf);
40   if (bar (p) != buf + 4
41       || memcmp (buf, "abcd\0\0\0\0\0", 10) != 0)
42     abort ();
43   memset (buf, 'v', 2);
44   memset (buf + 2, '\0', -2 + sizeof buf);
45   baz (p);
46   if (memcmp (buf, "vvabcd\0\0\0", 10) != 0)
47     abort ();
48   return 0;
49 }
50 
51 /* { dg-final { scan-tree-dump-times "strlen \\(" 0 "strlen" } } */
52 /* { dg-final { scan-tree-dump-times "memcpy \\(" 2 "strlen" } } */
53 /* { dg-final { scan-tree-dump-times "strcpy \\(" 1 "strlen" } } */
54 /* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */
55 /* { dg-final { scan-tree-dump-times "strchr \\(" 2 "strlen" } } */
56 /* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen" } } */
57 /* { dg-final { cleanup-tree-dump "strlen" } } */
58