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))
8 void
fn1(void)9 fn1 (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))
25 void
fn2(void)26 fn2 (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))
43 void
fn3(void)44 fn3 (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))
60 void
fn4(void)61 fn4 (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))
78 void
fn5(void)79 fn5 (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 
95 int
main(void)96 main (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