145
|
1 /* PR middle-end/91647 - missing -Warray-bounds accessing a zero-length array
|
|
2 of a declared object
|
|
3 { dg-do "compile" }
|
|
4 { dg-options "-O2 -Wall" } */
|
|
5
|
|
6 typedef __INT16_TYPE__ int16_t;
|
|
7 typedef __INT32_TYPE__ int32_t;
|
|
8
|
|
9 void sink (void*);
|
|
10
|
|
11 /* Exercise a true flexible member. */
|
|
12
|
|
13 struct AX
|
|
14 {
|
|
15 int32_t n;
|
|
16 int16_t ax[]; // { dg-message "while referencing 'ax'" "member" }
|
|
17 };
|
|
18
|
|
19 static void warn_ax_local (struct AX *p)
|
|
20 {
|
|
21 p->ax[0] = 0; // { dg-warning "\\\[-Warray-bounds" }
|
|
22 p->ax[1] = 1; // { dg-warning "\\\[-Warray-bounds" }
|
|
23 }
|
|
24
|
|
25 static void nowarn_ax_extern (struct AX *p)
|
|
26 {
|
|
27 p->ax[0] = 0; p->ax[99] = 99; p->ax[999] = 999; p->ax[9999] = 9999;
|
|
28 }
|
|
29
|
|
30 static void warn_ax_local_buf (struct AX *p)
|
|
31 {
|
|
32 p->ax[0] = 4; p->ax[1] = 5;
|
|
33
|
|
34 p->ax[2] = 6; // { dg-warning "\\\[-Warray-bounds" }
|
|
35 p->ax[3] = 7; // { dg-warning "\\\[-Warray-bounds" }
|
|
36 p->ax[4] = 8; // { dg-warning "\\\[-Warray-bounds" }
|
|
37 }
|
|
38
|
|
39 static void warn_ax_extern_buf (struct AX *p)
|
|
40 {
|
|
41 p->ax[0] = 9; p->ax[1] = 10; p->ax[2] = 11;
|
|
42
|
|
43 p->ax[3] = 12; // { dg-warning "\\\[-Warray-bounds" }
|
|
44 p->ax[4] = 13; // { dg-warning "\\\[-Warray-bounds" }
|
|
45 p->ax[5] = 14; // { dg-warning "\\\[-Warray-bounds" }
|
|
46 }
|
|
47
|
|
48 static void nowarn_ax_extern_bufx (struct AX *p)
|
|
49 {
|
|
50 p->ax[0] = 0; p->ax[99] = 99; p->ax[999] = 999; p->ax[9999] = 9999;
|
|
51 }
|
|
52
|
|
53 static void nowarn_ax_ref (struct AX *p)
|
|
54 {
|
|
55 p->ax[0] = 0; p->ax[99] = 99; p->ax[999] = 999; p->ax[9999] = 9999;
|
|
56 }
|
|
57
|
|
58 void test_ax (struct AX *p, unsigned n)
|
|
59 {
|
|
60 {
|
|
61 struct AX sax; // { dg-message "defined here" "struct definition" }
|
|
62 warn_ax_local (&sax);
|
|
63 sink (&sax);
|
|
64 }
|
|
65
|
|
66 {
|
|
67 extern
|
|
68 struct AX xsax;
|
|
69 nowarn_ax_extern (&xsax);
|
|
70 sink (&xsax);
|
|
71 }
|
|
72
|
|
73 {
|
|
74 /* Verify out-of-bounds access to the local BUF is diagnosed. */
|
|
75 char ax_buf_p2[sizeof (struct AX) + 2 * sizeof (int16_t)];
|
|
76 warn_ax_local_buf ((struct AX*) ax_buf_p2);
|
|
77 sink (ax_buf_p2);
|
|
78 }
|
|
79
|
|
80 {
|
|
81 /* Verify out-of-bounds access to the extern BUF with a known
|
|
82 bound is diagnosed. */
|
|
83 extern char ax_buf_p3[sizeof (struct AX) + 3 * sizeof (int16_t)];
|
|
84 warn_ax_extern_buf ((struct AX*) ax_buf_p3);
|
|
85 sink (ax_buf_p3);
|
|
86 }
|
|
87
|
|
88 {
|
|
89 /* Verify that accesses to BUFX with an unknown bound are not
|
|
90 diagnosed. */
|
|
91 extern char bufx[];
|
|
92 nowarn_ax_extern_bufx ((struct AX*) bufx);
|
|
93 sink (bufx);
|
|
94 }
|
|
95
|
|
96 {
|
|
97 /* Verify that accesses to BUFN with a runtime bound are not
|
|
98 diagnosed. */
|
|
99 char bufn[n];
|
|
100 nowarn_ax_extern_bufx ((struct AX*) bufn);
|
|
101 sink (bufn);
|
|
102 }
|
|
103
|
|
104 nowarn_ax_ref (p);
|
|
105 }
|
|
106
|
|
107
|
|
108 /* Exercise a zero-length trailing member array. It's the same as above
|
|
109 except that extern declarations with no definitions are considered to
|
|
110 have zero elements (they can't be initialized to have any). */
|
|
111
|
|
112 struct A0
|
|
113 {
|
|
114 int32_t n;
|
|
115 int16_t a0[0]; // { dg-message "while referencing 'a0'" "member" }
|
|
116 };
|
|
117
|
|
118 static void warn_a0_local (struct A0 *p)
|
|
119 {
|
|
120 p->a0[0] = 0; // { dg-warning "\\\[-Warray-bounds" }
|
|
121 p->a0[1] = 1; // { dg-warning "\\\[-Warray-bounds" }
|
|
122 }
|
|
123
|
|
124 static void warn_a0_extern (struct A0 *p)
|
|
125 {
|
|
126 p->a0[0] = 2; // { dg-warning "\\\[-Warray-bounds" }
|
|
127 p->a0[1] = 3; // { dg-warning "\\\[-Warray-bounds" }
|
|
128 }
|
|
129
|
|
130 static void warn_a0_local_buf (struct A0 *p)
|
|
131 {
|
|
132 p->a0[0] = 4; p->a0[1] = 5;
|
|
133
|
|
134 p->a0[2] = 6; // { dg-warning "\\\[-Warray-bounds" }
|
|
135 p->a0[3] = 7; // { dg-warning "\\\[-Warray-bounds" }
|
|
136 p->a0[4] = 8; // { dg-warning "\\\[-Warray-bounds" }
|
|
137 }
|
|
138
|
|
139 static void warn_a0_extern_buf (struct A0 *p)
|
|
140 {
|
|
141 p->a0[0] = 9; p->a0[1] = 10; p->a0[2] = 11;
|
|
142
|
|
143 p->a0[3] = 12; // { dg-warning "\\\[-Warray-bounds" }
|
|
144 p->a0[4] = 13; // { dg-warning "\\\[-Warray-bounds" }
|
|
145 p->a0[5] = 14; // { dg-warning "\\\[-Warray-bounds" }
|
|
146 }
|
|
147
|
|
148 static void nowarn_a0_extern_bufx (struct A0 *p)
|
|
149 {
|
|
150 p->a0[0] = 0; p->a0[99] = 99; p->a0[999] = 999; p->a0[9999] = 9999;
|
|
151 }
|
|
152
|
|
153 static void nowarn_a0_ref (struct A0 *p)
|
|
154 {
|
|
155 p->a0[0] = 0; p->a0[99] = 99; p->a0[999] = 999; p->a0[9999] = 9999;
|
|
156 }
|
|
157
|
|
158 void test_a0 (struct A0 *p, unsigned n)
|
|
159 {
|
|
160 {
|
|
161 struct A0 sa0; // { dg-message "defined here" "struct definition" }
|
|
162 warn_a0_local (&sa0);
|
|
163 sink (&sa0);
|
|
164 }
|
|
165
|
|
166 {
|
|
167 extern
|
|
168 struct A0 xsa0; // { dg-message "defined here" "struct definition" }
|
|
169 warn_a0_extern (&xsa0);
|
|
170 sink (&xsa0);
|
|
171 }
|
|
172
|
|
173 {
|
|
174 /* Verify out-of-bounds access to the local BUF is diagnosed. */
|
|
175 char a0_buf_p2[sizeof (struct A0) + 2 * sizeof (int16_t)];
|
|
176 warn_a0_local_buf ((struct A0*) a0_buf_p2);
|
|
177 sink (a0_buf_p2);
|
|
178 }
|
|
179
|
|
180 {
|
|
181 /* Verify out-of-bounds access to the extern BUF with a known
|
|
182 bound is diagnosed. */
|
|
183 extern char a0_buf_p3[sizeof (struct A0) + 3 * sizeof (int16_t)];
|
|
184 warn_a0_extern_buf ((struct A0*) a0_buf_p3);
|
|
185 sink (a0_buf_p3);
|
|
186 }
|
|
187
|
|
188 {
|
|
189 /* Verify that accesses to BUFX with an unknown bound are not
|
|
190 diagnosed. */
|
|
191 extern char bufx[];
|
|
192 nowarn_a0_extern_bufx ((struct A0*) bufx);
|
|
193 sink (bufx);
|
|
194 }
|
|
195
|
|
196 {
|
|
197 /* Verify that accesses to BUFN with a runtime bound are not
|
|
198 diagnosed. */
|
|
199 char bufn[n];
|
|
200 nowarn_a0_extern_bufx ((struct A0*) bufn);
|
|
201 sink (bufn);
|
|
202 }
|
|
203
|
|
204 nowarn_a0_ref (p);
|
|
205 }
|
|
206
|
|
207
|
|
208 /* Exercise a one-element trailing member array. It's the same as above
|
|
209 except that it has exactly one element. */
|
|
210
|
|
211 struct A1
|
|
212 {
|
|
213 int32_t n;
|
|
214 int16_t a1[1]; // { dg-message "while referencing 'a1'" }
|
|
215 };
|
|
216
|
|
217 static void warn_a1_local_noinit (struct A1 *p)
|
|
218 {
|
|
219 p->a1[0] = 0;
|
|
220 p->a1[1] = 1; // { dg-warning "\\\[-Warray-bounds" }
|
|
221 p->a1[2] = 2; // { dg-warning "\\\[-Warray-bounds" }
|
|
222 }
|
|
223
|
|
224 static void warn_a1_extern (struct A1 *p)
|
|
225 {
|
|
226 p->a1[0] = 0;
|
|
227 p->a1[1] = 1; // { dg-warning "\\\[-Warray-bounds" }
|
|
228 p->a1[2] = 2; // { dg-warning "\\\[-Warray-bounds" }
|
|
229 }
|
|
230
|
|
231 static void warn_a1_init (struct A1 *p)
|
|
232 {
|
|
233 p->a1[0] = 0;
|
|
234 p->a1[1] = 1; // { dg-warning "\\\[-Warray-bounds" }
|
|
235 p->a1[2] = 2; // { dg-warning "\\\[-Warray-bounds" }
|
|
236 }
|
|
237
|
|
238 static void warn_a1_local_buf (struct A1 *p)
|
|
239 {
|
|
240 p->a1[0] = 0; p->a1[1] = 1; p->a1[2] = 2; p->a1[3] = 3;
|
|
241
|
|
242 p->a1[4] = 4; // { dg-warning "\\\[-Warray-bounds" }
|
|
243 }
|
|
244
|
|
245 static void warn_a1_extern_buf (struct A1 *p)
|
|
246 {
|
|
247 p->a1[0] = 0; p->a1[1] = 1; p->a1[2] = 2; p->a1[3] = 3; p->a1[4] = 4;
|
|
248
|
|
249 p->a1[5] = 5; // { dg-warning "\\\[-Warray-bounds" }
|
|
250 }
|
|
251
|
|
252 static void nowarn_a1_extern_bufx (struct A1 *p)
|
|
253 {
|
|
254 p->a1[0] = 0; p->a1[99] = 99; p->a1[999] = 999; p->a1[9999] = 9999;
|
|
255 }
|
|
256
|
|
257 static void nowarn_a1_ref (struct A1 *p)
|
|
258 {
|
|
259 p->a1[0] = 0; p->a1[99] = 99; p->a1[999] = 999; p->a1[9999] = 9999;
|
|
260 }
|
|
261
|
|
262 void test_a1 (struct A1 *p, unsigned n)
|
|
263 {
|
|
264 {
|
|
265 struct A1 a1;
|
|
266 warn_a1_local_noinit (&a1);
|
|
267 sink (&a1);
|
|
268 }
|
|
269
|
|
270 {
|
|
271 extern struct A1 a1x;
|
|
272 warn_a1_extern (&a1x);
|
|
273 sink (&a1x);
|
|
274 }
|
|
275 {
|
|
276 struct A1 a1 = { 0, { 1 } };
|
|
277 warn_a1_init (&a1);
|
|
278 sink (&a1);
|
|
279 }
|
|
280
|
|
281 {
|
|
282 /* Verify out-of-bounds access to the local BUF is diagnosed. */
|
|
283 char buf_p2[sizeof (struct A1) + 2 * sizeof (int16_t)];
|
|
284 warn_a1_local_buf ((struct A1*) buf_p2);
|
|
285 sink (buf_p2);
|
|
286 }
|
|
287
|
|
288 {
|
|
289 /* Verify out-of-bounds access to the extern BUF with a known
|
|
290 bound is diagnosed. */
|
|
291 extern char a1_buf_p3[sizeof (struct A1) + 3 * sizeof (int16_t)];
|
|
292 warn_a1_extern_buf ((struct A1*) a1_buf_p3);
|
|
293 sink (a1_buf_p3);
|
|
294 }
|
|
295
|
|
296 {
|
|
297 /* Verify that accesses to BUFX with an unknown bound are not
|
|
298 diagnosed. */
|
|
299 extern char bufx[];
|
|
300 nowarn_a1_extern_bufx ((struct A1*) bufx);
|
|
301 sink (bufx);
|
|
302 }
|
|
303
|
|
304 {
|
|
305 /* Verify that accesses to BUFN with a runtime bound are not
|
|
306 diagnosed. */
|
|
307 char bufn[n];
|
|
308 nowarn_a1_extern_bufx ((struct A1*) bufn);
|
|
309 sink (bufn);
|
|
310 }
|
|
311
|
|
312 nowarn_a1_ref (p);
|
|
313 }
|
|
314
|
|
315
|
|
316 /* Exercise a two-element trailing member array. It's treated
|
|
317 the same as an interior array member. */
|
|
318
|
|
319 struct A2
|
|
320 {
|
|
321 int32_t n;
|
|
322 int16_t a2[2]; // { dg-message "while referencing 'a2'" }
|
|
323 };
|
|
324
|
|
325 static void warn_a2_noinit (struct A2 *p)
|
|
326 {
|
|
327 p->a2[0] = 0; p->a2[1] = 1;
|
|
328
|
|
329 p->a2[2] = 2; // { dg-warning "\\\[-Warray-bounds" }
|
|
330 }
|
|
331
|
|
332 static void warn_a2_init (struct A2 *p)
|
|
333 {
|
|
334 p->a2[0] = 0; p->a2[1] = 1;
|
|
335
|
|
336 p->a2[2] = 2; // { dg-warning "\\\[-Warray-bounds" }
|
|
337 p->a2[9] = 9; // { dg-warning "\\\[-Warray-bounds" }
|
|
338 }
|
|
339
|
|
340 static void warn_a2_ref (struct A2 *p)
|
|
341 {
|
|
342 p->a2[0] = 0; p->a2[1] = 1;
|
|
343
|
|
344 p->a2[2] = 2; // { dg-warning "\\\[-Warray-bounds" }
|
|
345 p->a2[9] = 9; // { dg-warning "\\\[-Warray-bounds" }
|
|
346 }
|
|
347
|
|
348 void test_a2 (struct A2 *p)
|
|
349 {
|
|
350 {
|
|
351 struct A2 a2;
|
|
352 warn_a2_noinit (&a2);
|
|
353 sink (&a2);
|
|
354 }
|
|
355
|
|
356 {
|
|
357 struct A2 a2 = { 0, { 1, 2 } };
|
|
358 warn_a2_init (&a2);
|
|
359 sink (&a2);
|
|
360 }
|
|
361
|
|
362 warn_a2_ref (p);
|
|
363 }
|