1 /* Test to verify that a strlen() call with a pointer to a dynamic type
2    doesn't make assumptions based on the static type of the original
3    pointer.  See g++.dg/init/strlen.C for the corresponding C++ test.  */
4 
5 struct A { int i; char a[1]; void (*p)(); };
6 struct B { char a[sizeof (struct A) - __builtin_offsetof (struct A, a)]; };
7 
8 __attribute__ ((noipa)) void
init(char * d,const char * s)9 init (char *d, const char *s)
10 {
11   __builtin_strcpy (d, s);
12 }
13 
14 struct B b;
15 
16 __attribute__ ((noipa)) void
test_dynamic_type(struct A * p)17 test_dynamic_type (struct A *p)
18 {
19   /* The following call is undefined because it writes past the end
20      of the p->a subobject, but the corresponding GIMPLE considers
21      it valid and there's apparently no way to distinguish invalid
22      cases from ones like it that might be valid.  If/when GIMPLE
23      changes to make this possible this test can be removed.  */
24   char *q = (char*)__builtin_memcpy (p->a, &b, sizeof b);
25 
26   init (q, "foobar");
27 
28   if (6 != __builtin_strlen (q))
29     __builtin_abort();
30 }
31 
main(void)32 int main (void)
33 {
34   struct A *p = (struct A*)__builtin_malloc (sizeof *p);
35   test_dynamic_type (p);
36   return 0;
37 }
38