1 /* PR middle-end/91458 - inconsistent warning for writing past the end
2 of an array member
3 { dg-do compile }
4 { dg-options "-O2 -Wall -Wno-array-bounds" } */
5
6 #define NOIPA __attribute__ ((noipa))
7
8 void sink (void*);
9
10 // Exercise flexible array members.
11
12 struct Ax
13 {
14 char n;
15 char a[]; // { dg-message "at offset \[0-2\] to object 'Ax::a' declared here" "note: flexarray" }
16 };
17
18 // Verify warning for a definition with no initializer.
19 Ax ax_;
20
gax_()21 NOIPA void gax_ ()
22 {
23 ax_.a[0] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
24 ax_.a[1] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
25 ax_.a[2] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
26 }
27
28 // Verify warning for access to a definition with an initializer that doesn't
29 // initialize the flexible array member.
30 Ax ax0 = { 0 };
31
gax0()32 NOIPA void gax0 ()
33 {
34 ax0.a[0] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
35 ax0.a[1] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
36 ax0.a[2] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
37 }
38
39 // Verify warning for access to a definition with an initializer that
40 // initializes the flexible array member to empty.
41 Ax ax0_ = { 0, { } };
42
gax0_()43 NOIPA void gax0_ ()
44 {
45 ax0_.a[0] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
46 ax0_.a[1] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
47 ax0_.a[2] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
48 }
49
50 // Verify warning for out-of-bounds accesses to a definition with
51 // an initializer.
52 Ax ax1 = { 1, { 0 } };
53
gax1()54 NOIPA void gax1 ()
55 {
56 ax1.a[0] = 0;
57 ax1.a[1] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
58 ax1.a[2] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
59 }
60
61 Ax ax2 = { 2, { 1, 0 } };
62
gax2()63 NOIPA void gax2 ()
64 {
65 ax2.a[0] = 0;
66 ax2.a[1] = 0;
67 ax2.a[2] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
68 }
69
70
71 // Verify no warning for an unknown struct object.
gaxp(Ax * p)72 NOIPA void gaxp (Ax *p)
73 {
74 p->a[0] = 0;
75 p->a[3] = 0;
76 p->a[9] = 0;
77 }
78
79
80 // Verify no warning for an extern struct object whose array may be
81 // initialized to any number of elements.
82 extern Ax axx;
83
gaxx()84 NOIPA void gaxx ()
85 {
86 axx.a[0] = 0;
87 axx.a[3] = 0;
88 axx.a[9] = 0;
89 }
90
91 // Exercise zero-length array members.
92
93 struct A0
94 {
95 char n;
96 char a[0]; // { dg-message "at offset \[0-2\] to object 'A0::a' with size 0 declared here" "note: trailing zero-length array" }
97 };
98
99 // Verify warning for a definition with no initializer.
100 A0 a0_;
101
ga0_()102 NOIPA void ga0_ ()
103 {
104 a0_.a[0] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
105 a0_.a[1] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
106 a0_.a[2] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
107 }
108
109 // Verify warning for access to a definition with an initializer that doesn't
110 // initialize the flexible array member.
111 A0 a00 = { 0 };
112
ga00()113 NOIPA void ga00 ()
114 {
115 a00.a[0] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
116 a00.a[1] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
117 a00.a[2] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
118 }
119
120 // Verify warning for access to a definition with an initializer that
121 // initializes the flexible array member to empty.
122 A0 a00_ = { 0, { } };
123
ga00_()124 NOIPA void ga00_ ()
125 {
126 a00_.a[0] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
127 a00_.a[1] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
128 a00_.a[2] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
129 }
130
131 // The following are rejected with
132 // error: too many initializers for 'char [0]'
133 // A0 a01 = { 1, { 0 } };
134 // A0 a02 = { 2, { 1, 0 } };
135
136
137 // Verify no warning for an unknown struct object.
ga0p(A0 * p)138 NOIPA void ga0p (A0 *p)
139 {
140 p->a[0] = 0;
141 p->a[3] = 0;
142 p->a[9] = 0;
143 }
144
145
146 // Verify warning for an extern struct object which (unlike a true
147 // flexible array member) may not be initialized.
148 extern A0 a0x;
149
ga0x()150 NOIPA void ga0x ()
151 {
152 a0x.a[0] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
153 a0x.a[3] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
154 a0x.a[9] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
155 }
156
157
158 // Exercise trailing one-element array members.
159
160 struct A1
161 {
162 char n;
163 char a[1]; // { dg-message "at offset \[1-9\] to object 'A1::a' with size 1 declared here" "note: trailing one-element array" }
164 };
165
166 // Verify warning for a definition with no initializer.
167 A1 a1_;
168
ga1_()169 NOIPA void ga1_ ()
170 {
171 a1_.a[0] = 0;
172 a1_.a[1] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
173 a1_.a[2] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
174 }
175
176 // Verify warning for access to a definition with an initializer that doesn't
177 // initialize the one-element array member.
178 A1 a1__ = { 0 };
179
ga1__()180 NOIPA void ga1__ ()
181 {
182 a1__.a[0] = 0;
183 a1__.a[1] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
184 a1__.a[2] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
185 }
186
187 // Verify warning for access to a definition with an initializer that
188 // initializes the one-element array member to empty.
189 A1 a1_0 = { 0, { } };
190
ga1_0_()191 NOIPA void ga1_0_ ()
192 {
193 a1_0.a[0] = 0;
194 a1_0.a[1] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
195 a1_0.a[2] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
196 }
197
198 // Verify warning for access to a definition with an initializer that
199 // initializes the one-element array member.
200 A1 a1_1 = { 0, { 1 } };
201
ga1_1()202 NOIPA void ga1_1 ()
203 {
204 a1_1.a[0] = 0;
205 a1_1.a[1] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
206 a1_1.a[2] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
207 }
208
209
210 // Verify no warning for an unknown struct object.
ga1p(A1 * p)211 NOIPA void ga1p (A1 *p)
212 {
213 p->a[0] = 0;
214 p->a[3] = 0;
215 p->a[9] = 0;
216 }
217
218
219 // Verify warning for an extern struct object. Similar to the zero-length
220 // array case, a one-element trailing array can be initialized to at most
221 // a single element.
222 extern A1 a1x;
223
ga1x()224 NOIPA void ga1x ()
225 {
226 a1x.a[0] = 0;
227 a1x.a[3] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
228 a1x.a[9] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
229 }
230
231 // Exercise interior one-element array members (verify they're not
232 // treated as trailing.
233
234 struct A1i
235 {
236 char n;
237 char a[1]; // { dg-message "at offset \[1-9\] to object 'A1i::a' with size 1 declared here" "note: interior one-element array" }
238 char x;
239 };
240
241 // Verify warning for a definition with no initializer.
242 A1i a1i_;
243
ga1i_()244 NOIPA void ga1i_ ()
245 {
246 a1i_.a[0] = 0;
247 a1i_.a[1] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
248 a1i_.a[2] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
249 }
250
251 // Verify warning for access to a definition with an initializer that doesn't
252 // initialize the one-element array member.
253 A1i a1i__ = { 0 };
254
ga1i__()255 NOIPA void ga1i__ ()
256 {
257 a1i__.a[0] = 0;
258 a1i__.a[1] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
259 a1i__.a[2] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
260 }
261
262 // Verify warning for access to a definition with an initializer that
263 // initializes the one-element array member to empty.
264 A1 a1i_0 = { 0, { } };
265
ga1i_0_()266 NOIPA void ga1i_0_ ()
267 {
268 a1i_0.a[0] = 0;
269 a1i_0.a[1] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
270 a1i_0.a[2] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
271 }
272
273 // Verify warning for access to a definition with an initializer that
274 // initializes the one-element array member.
275 A1 a1i_1 = { 0, { 1 } };
276
ga1i_1()277 NOIPA void ga1i_1 ()
278 {
279 a1i_1.a[0] = 0;
280 a1i_1.a[1] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
281 a1i_1.a[2] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
282 }
283
284
285 // Verify no warning for an unknown struct object.
ga1ip(A1i * p)286 NOIPA void ga1ip (A1i *p)
287 {
288 p->a[0] = 0;
289 p->a[3] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
290 p->a[9] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
291 }
292
293
294 // Verify no warning for an extern struct object.
295 extern A1i a1ix;
296
ga1ix()297 NOIPA void ga1ix ()
298 {
299 a1ix.a[0] = 0;
300 a1ix.a[3] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
301 a1ix.a[9] = 0; // { dg-warning "\\\[-Wstringop-overflow" }
302 }
303
304
305 // Verify non-POD classes with flexible array members.
306
307 struct Bx
308 {
309 char n;
310 char a[]; // { dg-message "at offset 0 to object 'Bx::a' declared here" "note: flexarray class member" }
311
312 // Verify the warning for a constant.
BxBx313 Bx () { a[0] = 0; } // { dg-warning "\\\[-Wstringop-overflow" }
314
315 // And also for a non-constant. Regardless of the subscript, the array
316 // of the object in function gxi() below has a zero size.
BxBx317 Bx (int i) { a[i] = 0; } // { dg-warning "\\\[-Wstringop-overflow" }
318 };
319
gbx(void)320 NOIPA void gbx (void)
321 {
322 struct Bx bx;
323 sink (&bx);
324 }
325
gbxi(int i)326 NOIPA void gbxi (int i)
327 {
328 struct Bx bxi (i);
329 sink (&bxi);
330 }
331
332 struct B0
333 {
334 char n;
335 char a[0]; // { dg-message "at offset 0 to object 'B0::a' with size 0 declared here" "note: zero-length trailing array class member" }
336
B0B0337 B0 () { a[0] = 0; } // { dg-warning "\\\[-Wstringop-overflow" }
338 };
339
340
gb0(void)341 NOIPA void gb0 (void)
342 {
343 struct B0 b0;
344 sink (&b0);
345 }
346
347
348 struct B1
349 {
350 char n;
351 char a[1]; // { dg-message "at offset 1 to object 'B1::a' with size 1 declared here" "note: one-element trailing array class member" }
352
B1B1353 B1 () { a[1] = 0; } // { dg-warning "\\\[-Wstringop-overflow" }
354 };
355
gb1(void)356 NOIPA void gb1 (void)
357 {
358 struct B1 b1;
359 sink (&b1);
360 }
361
362
363 struct B123
364 {
365 char a[123]; // { dg-message "at offset 123 to object 'B123::a' with size 123 declared here" "note: large trailing array class member" }
366
B123B123367 B123 () { a[123] = 0; } // { dg-warning "\\\[-Wstringop-overflow" }
368 };
369
gb123(void)370 NOIPA void gb123 (void)
371 {
372 struct B123 b123;
373 sink (&b123);
374 }
375
376
377 struct B234
378 {
379 char a[234]; // { dg-message "at offset 234 to object 'B234::a' with size 234 declared here" "note: large trailing array class member" }
380
B234B234381 B234 (int i) { a[i] = 0; } // { dg-warning "\\\[-Wstringop-overflow" }
382 };
383
g234(void)384 NOIPA void g234 (void)
385 {
386 struct B234 b234 (234);
387 sink (&b234);
388 }
389