1 // Test to verify that the strlen() optimization doesn't make assumptions
2 // about the static type of the object pointed to by its argument.  See
3 // the following thread for background:
4 //   https://gcc.gnu.org/ml/gcc-patches/2018-08/msg00260.html
5 
6 // { dg-do run }
7 // { dg-options "-O2 -Wall -fdump-tree-optimized" }
8 
9 typedef __SIZE_TYPE__ size_t;
10 
11 void *operator new[] (size_t, void *p) { return p; }
12 
13 struct S { int x; char a[1]; char b[64]; };
14 
15 __attribute__ ((noipa)) void
init(char * s)16 init (char *s)
17 {
18   *s++ = '1';
19   *s++ = '\0';
20 }
21 
22 __attribute__ ((noipa)) void
test_dynamic_type(S * p)23 test_dynamic_type (S *p)
24 {
25   // The placement new call below isn't strictly valid because it
26   // creates an object that is larger than the space of the p->a
27   // subobject in which it is created.  However, the corresponding
28   // GIMPLE considers it valid and there's apparently no way to
29   // distinguish invalid cases from ones like it that might be valid.
30   // If/when GIMPLE changes to make this possible this test can be
31   // removed.
32   char *q = new (p->a) char [16];
33 
34   init (q);
35 
36   if (0 == __builtin_strlen (q))
37     __builtin_abort();
38 }
39 
main()40 int main ()
41 {
42   test_dynamic_type (new S);
43 }
44