1  /* { dg-do run } */
       2  /* { dg-options "-O2 -fdump-tree-strlen" } */
       3  
       4  #include "strlenopt.h"
       5  
       6  __attribute__((noinline, noclone)) char *
       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 *
      15  bar (char *p)
      16  {
      17    memcpy (p, "abcd", 5);
      18    return strchr (p, '\0');
      19  }
      20  
      21  __attribute__((noinline, noclone)) void
      22  baz (char *p)
      23  {
      24    char *e = strchr (p, '\0');
      25    strcat (e, "abcd");
      26  }
      27  
      28  char buf[64];
      29  
      30  int
      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 \\(" 2 "strlen1" } } */
      52  /* { dg-final { scan-tree-dump-times "memcpy \\(" 2 "strlen1" } } */
      53  /* { dg-final { scan-tree-dump-times "strcpy \\(" 1 "strlen1" } } */
      54  /* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen1" } } */
      55  /* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen1" } } */
      56  /* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen1" } } */