1/* { dg-do run } */
2/* { dg-options "-fsanitize=bounds -Wall -Wextra -Wno-unused -Wno-array-bounds" } */
3
4/* Test flexible array member-like arrays.  Normal flexible array members
5   are tested in bounds-1.c.  Test non-strict mode.  */
6
7__attribute__ ((noinline, noclone))
8void
9fn1 (void)
10{
11  volatile struct S { char a[1]; char b; } s;
12  volatile int i;
13  asm ("" : : "r" (&s.a) : "memory");
14  i = s.a[0]; // OK
15  asm ("" : : "r" (&s.a) : "memory");
16  i = s.a[1]; // error
17  volatile struct S *p = &s;
18  asm ("" : : "r" (&p->a) : "memory");
19  i = p->a[0]; // OK
20  asm ("" : : "r" (&p->a) : "memory");
21  i = p->a[1]; // error
22}
23
24__attribute__ ((noinline, noclone))
25void
26fn2 (void)
27{
28  struct S { int c; char d[4]; };
29  volatile struct T { int e; struct S f; int g; } t;
30  volatile int i;
31  asm ("" : : "r" (&t.f.d) : "memory");
32  i = t.f.d[3]; // OK
33  asm ("" : : "r" (&t.f.d) : "memory");
34  i = t.f.d[4]; // error
35  volatile struct T *p = &t;
36  asm ("" : : "r" (&p->f.d) : "memory");
37  i = p->f.d[3]; // OK
38  asm ("" : : "r" (&p->f.d) : "memory");
39  i = p->f.d[4]; // error
40}
41
42__attribute__ ((noinline, noclone))
43void
44fn3 (void)
45{
46  volatile struct S { char b; char a[1]; } s;
47  volatile int i;
48  asm ("" : : "r" (&s.a) : "memory");
49  i = s.a[0]; // OK
50  asm ("" : : "r" (&s.a) : "memory");
51  i = s.a[1]; // error
52  volatile struct S *p = &s;
53  asm ("" : : "r" (&p->a) : "memory");
54  i = p->a[0]; // OK
55  asm ("" : : "r" (&p->a) : "memory");
56  i = p->a[1]; // error in strict mode
57}
58
59__attribute__ ((noinline, noclone))
60void
61fn4 (void)
62{
63  volatile struct S { char b; char a[1]; } s;
64  volatile struct T { struct S s; int i; } t;
65  volatile int i;
66  asm ("" : : "r" (&t.s.a) : "memory");
67  i = t.s.a[0]; // OK
68  asm ("" : : "r" (&t.s.a) : "memory");
69  i = t.s.a[1]; // error
70  volatile struct T *pt = &t;
71  asm ("" : : "r" (&pt->s.a) : "memory");
72  i = pt->s.a[0]; // OK
73  asm ("" : : "r" (&pt->s.a) : "memory");
74  i = pt->s.a[1]; // error
75}
76
77__attribute__ ((noinline, noclone))
78void
79fn5 (void)
80{
81  volatile struct S { char b; char a[1]; } s;
82  volatile struct U { int a; struct S s; } u;
83  volatile int i;
84  asm ("" : : "r" (&u.s.a) : "memory");
85  i = u.s.a[0]; // OK
86  asm ("" : : "r" (&u.s.a) : "memory");
87  i = u.s.a[1]; // error
88  volatile struct U *pu = &u;
89  asm ("" : : "r" (&pu->s.a) : "memory");
90  i = pu->s.a[0]; // OK
91  asm ("" : : "r" (&pu->s.a) : "memory");
92  i = pu->s.a[1]; // error in strict mode
93}
94
95int
96main (void)
97{
98  fn1 ();
99  fn2 ();
100  fn3 ();
101  fn4 ();
102  fn5 ();
103  return 0;
104}
105
106/* { dg-output "index 1 out of bounds for type 'char \\\[1\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
107/* { dg-output "\[^\n\r]*index 1 out of bounds for type 'char \\\[1\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
108/* { dg-output "\[^\n\r]*index 4 out of bounds for type 'char \\\[4\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
109/* { dg-output "\[^\n\r]*index 4 out of bounds for type 'char \\\[4\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
110/* { dg-output "\[^\n\r]*index 1 out of bounds for type 'char \\\[1\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
111/* { dg-output "\[^\n\r]*index 1 out of bounds for type 'char \\\[1\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
112/* { dg-output "\[^\n\r]*index 1 out of bounds for type 'char \\\[1\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
113/* { dg-output "\[^\n\r]*index 1 out of bounds for type 'char \\\[1\\\]'" } */
114