]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/testsuite/c-c++-common/Warray-bounds-3.c
Correct handling of variable offset minus constant in -Warray-bounds [PR100137]
[thirdparty/gcc.git] / gcc / testsuite / c-c++-common / Warray-bounds-3.c
CommitLineData
cc8bea0a
MS
1/* Exercise that -Warray-bounds is issued for out-of-bounds offsets
2 in calls to built-in functions.
3 { dg-do compile }
af3fa359 4 { dg-options "-O2 -Wno-stringop-overflow -Warray-bounds -ftrack-macro-expansion=0" } */
cc8bea0a
MS
5
6#include "../gcc.dg/range.h"
7
8#if __cplusplus
9# define restrict __restrict
10extern "C" {
11#endif
12
13extern void* memcpy (void* restrict, const void* restrict, size_t);
14extern void* mempcpy (void* restrict, const void* restrict, size_t);
15extern void* memmove (void*, const void*, size_t);
16
17extern char* stpcpy (char* restrict, const char* restrict);
18
19extern char* strcat (char* restrict, const char* restrict);
20extern char* strcpy (char* restrict, const char* restrict);
21extern char* strncpy (char* restrict, const char* restrict, size_t);
22
23#if __cplusplus
24} /* extern "C" */
25#endif
26
27void sink (void*, ...);
28
29#define CAT(x, y) x ## y
30#define CONCAT(x, y) CAT (x, y)
31#define UNIQUE_NAME(x) CONCAT(x, __LINE__)
32
33#define T(type, N, dst, src, n) do { \
34 extern type UNIQUE_NAME (a)[N]; \
35 type *a = UNIQUE_NAME (a); \
36 type *pd = (dst); \
37 const type *ps = (src); \
38 FUNC (pd, ps, n); \
39 sink (a, pd, ps); \
40 } while (0)
41
42
43void test_memcpy_bounds (char *d, const char *s, size_t n)
44{
45#define FUNC memcpy
46
47 /* Verify that invalid offsets into an array of known size are
48 detected. */
49
50 T (char, 1, a + SR (DIFF_MIN, -1), s, n); /* { dg-warning "offset \\\[-\[0-9\]+, -1] is out of the bounds \\\[0, 1] of object \[^\n\r]* with type .char ?\\\[1]" } */
51 T (char, 1, a + SR (-2, -1), s, n); /* { dg-warning "offset \\\[-2, -1] is out of the bounds \\\[0, 1] of object" } */
52 T (char, 1, a + SR (-2, 0), s, n);
53
54 T (char, 1, a + UR (0, 1), s, n);
55 T (char, 1, a + UR (0, 2), s, n);
56 T (char, 1, a + UR (1, 2), s, n);
57 T (char, 1, a + UR (2, 3), s, n); /* { dg-warning "offset \\\[2, 3] is out of the bounds \\\[0, 1] of object " } */
58 T (char, 1, a + UR (2, DIFF_MAX), s, n); /* { dg-warning "offset \\\[2, \[0-9\]+] is out of the bounds \\\[0, 1] of object " "memcpy" } */
59
60 /* Offsets in excess of DIFF_MAX are treated as negative even if
61 they appear as large positive in the source. It would be nice
62 if they retained their type but unfortunately that's not how
63 it works so be prepared for both in case it even gets fixed. */
5e27f0d5 64 T (char, 1, a + UR (3, SIZE_MAX - 1), s, n); /* { dg-warning "offset \\\[3, -?\[0-9\]+] is out of the bounds \\\[0, 1] of object" "memcpy" } */
cc8bea0a
MS
65
66 /* Verify that invalid offsets into an array of unknown size are
67 detected. */
68 extern char arr[];
69 T (char, 1, arr + SR (DIFF_MIN, 0), s, n);
70 T (char, 1, arr + SR (DIFF_MIN + 1, -1), s, n); /* { dg-warning "offset \\\[-\[0-9\]+, -1] is out of the bounds of object " "memcpy" } */
71 T (char, 1, arr + SR (DIFF_MIN, 1), s, n);
72 T (char, 1, arr + SR (DIFF_MIN, DIFF_MAX), s, n);
73 T (char, 1, arr + SR ( -2, -1), s, n); /* { dg-warning "offset \\\[-2, -1] is out of the bounds of object " "memcpy" } */
74 T (char, 1, arr + SR ( -1, 0), s, n);
75 T (char, 1, arr + SR ( -1, 1), s, n);
76 T (char, 1, arr + SR ( -1, DIFF_MAX - 1), s, n);
77 T (char, 1, arr + SR ( 0, 1), s, n);
78 T (char, 1, arr + SR ( 0, DIFF_MAX - 1), s, n);
79 T (char, 1, arr + SR ( 1, 2), s, n);
80 T (char, 1, arr + SR ( 1, DIFF_MAX - 1), s, n);
81
82 /* Verify that all offsets via a pointer to an uknown object are
83 accepted. */
84
85 /* Negative indices between [DIFF_MIN, DIFF_MAX] are valid since
86 the pointer to which the offset is applied can be at a positive
87 offset from the beginning of an object. */
88 T (char, 1, d + SR (DIFF_MIN, 0), s, n);
89 T (char, 1, d + SR (DIFF_MIN, -1), s, n);
90 T (char, 1, d + SR (DIFF_MIN, 1), s, n);
91 T (char, 1, d + SR (DIFF_MIN, DIFF_MAX - 1), s, n);
92 T (char, 1, d + SR ( -2, -1), s, n);
93 T (char, 1, d + SR ( -1, 0), s, n);
94 T (char, 1, d + SR ( -1, 1), s, n);
95 T (char, 1, d + SR ( -1, DIFF_MAX - 1), s, n);
96 T (char, 1, d + SR ( 0, 1), s, n);
97 T (char, 1, d + SR ( 0, DIFF_MAX - 1), s, n);
98 T (char, 1, d + SR ( 1, 2), s, n);
99 T (char, 1, d + SR ( 1, DIFF_MAX - 1), s, n);
100}
101
102/* Verify offsets in an anti-range. */
103
104void test_memcpy_bounds_anti_range (char *d, const char *s, size_t n)
105{
106 T (char, 9, a, a + SAR (-2, -1), 3);
107 T (char, 9, a, a + SAR (-1, 1), 3);
108 T (char, 9, a, a + SAR ( 0, 1), 3);
109 T (char, 9, a, a + SAR ( 0, 2), 3);
110 T (char, 9, a, a + SAR ( 0, 3), 3);
111 T (char, 9, a, a + SAR ( 0, 4), 3);
112 T (char, 9, a, a + SAR ( 0, 5), 3);
113 /* The initial source range is valid but the final range after the access
114 has complete cannot be. The value mentioned in the warning is the final
115 offset, i.e., 7 + 3. Including the whole final range because would be
116 confusing (the upper bound would either be negative or a very large
117 positive number) so only the lower bound is included. */
6889a3ac 118 T (char, 9, a, a + SAR ( 0, 6), 3); /* { dg-warning "forming offset 9 is out of the bounds \\\[0, 9] of object " "memcpy" } */
cc8bea0a
MS
119
120 /* This fails because the offset isn't represented as an SSA_NAME
121 but rather as a GIMPLE_PHI (offset, 0). With some effort it is
122 possible to extract the range from the PHI but it's not implemented
123 (yet). */
124 T (char, 9, a, a + SAR ( 1, 6), 3); /* { dg-warning "forming offset \\\[9, 0] is out of the bounds \\\[0, 9] of object " "memcpy" { xfail *-*-* } } */
125
56735d40
MS
126 /* The range of offsets is the union of [0, 1] and [7, PTRDIFF_MAX]
127 of which the first subrange is valid and thus no warming for memcpy
128 is issued. Similarly for the next test. */
129 T (char, 9, a, a + SAR ( 2, 6), 3);
130 T (char, 9, a, a + SAR ( 3, 6), 3);
cc8bea0a 131
6889a3ac
MS
132 T (char, 9, a, a + SAR (-1, 7), 3); /* { dg-warning "forming offset \\\[9, 10] is out of the bounds \\\[0, 9] of object " "memcpy" } */
133 T (char, 9, a, a + SAR (-2, 8), 3); /* { dg-warning "offset \\\[9, 11] is out of the bounds \\\[0, 9] of object " "memcpy" } */
134 T (char, 9, a, a + SAR (-3, 7), 5); /* { dg-warning "forming offset \\\[9, 12] is out of the bounds \\\[0, 9] of object " "memcpy" } */
cc8bea0a
MS
135
136 T (char, 9, a + SAR (-2, -1), a, 3);
137 T (char, 9, a + SAR (-1, 1), a, 3);
138 T (char, 9, a + SAR ( 0, 1), a, 3);
139 T (char, 9, a + SAR ( 0, 2), a, 3);
140 T (char, 9, a + SAR ( 0, 3), a, 3);
6889a3ac
MS
141 T (char, 9, a + SAR ( 0, 6), a, 3); /* { dg-warning "forming offset 9 is out of the bounds \\\[0, 9] of object " "memcpy" } */
142 T (char, 9, a + SAR (-1, 7), a, 3); /* { dg-warning "forming offset \\\[9, 10] is out of the bounds \\\[0, 9] of object " "memcpy" } */
143 T (char, 9, a + SAR (-2, 8), a, 3); /* { dg-warning "offset \\\[9, 11] is out of the bounds \\\[0, 9] of object " "memcpy" } */
cc8bea0a
MS
144
145 ptrdiff_t i = SAR (DIFF_MIN + 1, DIFF_MAX - 4);
146 T (char, 1, d, d + SAR (DIFF_MIN + 3, DIFF_MAX - 1), 3);
147 T (char, 1, d, d + SAR (DIFF_MIN + 3, DIFF_MAX - 3), 5);
148}
149
150/* Verify that pointer overflow in the computation done by memcpy
151 (i.e., offset + size) is detected and diagnosed. */
152
153void test_memcpy_overflow (char *d, const char *s, size_t n)
154{
155 extern char arr[];
156
157 /* Verify that offset overflow involving an array of unknown size
158 but known access size is detected. This works except with small
159 sizes that are powers of 2 due to bug . */
160 T (char, 1, arr + SR (DIFF_MAX - 1, DIFF_MAX), s, 1);
a1108556 161 T (char, 1, arr + SR (DIFF_MAX - 1, DIFF_MAX), s, 2); /* { dg-warning "\\\[-Warray-bounds" } */
cc8bea0a
MS
162 T (char, 1, arr + SR (DIFF_MAX - 2, DIFF_MAX), s, 3); /* { dg-warning "pointer overflow between offset \\\[\[0-9\]+, \[0-9\]+] and size 3 accessing array " "memcpy" } */
163 T (char, 1, arr + SR (DIFF_MAX - 4, DIFF_MAX), s, 5); /* { dg-warning "pointer overflow between offset \\\[\[0-9\]+, \[0-9\]+] and size 5 accessing array " "memcpy" } */
164}
165
166void test_memcpy_bounds_memarray_range (void)
167{
168#undef TM
169#define TM(mem, dst, src, n) \
170 do { \
171 struct MA { char a5[5]; int i; } ma; \
172 sink (&ma); /* Initialize arrays. */ \
173 memcpy (dst, src, n); \
174 sink (&ma); \
175 } while (0)
176
177 ptrdiff_t i = SR (1, 2);
178
179 TM (ma.a5, ma.a5 + i, ma.a5, 1);
180 TM (ma.a5, ma.a5 + i, ma.a5, 3);
a1108556 181 TM (ma.a5, ma.a5 + i, ma.a5, 5); /* { dg-warning "\\\[-Warray-bounds" } */
cc8bea0a
MS
182 TM (ma.a5, ma.a5 + i, ma.a5, 7); /* diagnosed with -Warray-bounds=2 */
183}
184
185void test_memmove_bounds (char *d, const char *s, size_t n)
186{
187#undef FUNC
188#define FUNC memmove
189
190 T (char, 1, a + SR (DIFF_MIN + 1, -1), s, n); /* { dg-warning "offset \\\[-\[0-9\]+, -1] is out of the bounds \\\[0, 1] of object \[^\n\r]+ with type .char ?\\\[1]" } */
191 T (char, 1, a + SR (-2, -1), s, n); /* { dg-warning "offset \\\[-2, -1] is out of the bounds \\\[0, 1] of object" } */
192 T (char, 1, a + SR (-2, 0), s, n);
193
194 const int *pi = (const int*)s;
195 T (int, 2, a + SR (-1, 1), pi, n);
196 T (int, 2, a + SR (-1, 2), pi, n);
197 T (int, 2, a + SR ( 0, 2), pi, n);
198 T (int, 2, a + SR ( 0, 3), pi, n);
199 T (int, 2, a + SR ( 1, 3), pi, n);
200 T (int, 2, a + SR ( 2, 3), pi, n);
201
12b38cca
EB
202 const int32_t *pi32 = (const int32_t*)s;
203 T (int32_t, 2, a + SR ( 3, 4), pi32, n); /* { dg-warning "offset \\\[12, 16] is out of the bounds \\\[0, 8] of object .\[^\n\r]+. with type .int32_t ?\\\[2]." } */
cc8bea0a
MS
204}
205
206
207void test_mempcpy_bounds (char *d, const char *s, size_t n)
208{
209#undef FUNC
210#define FUNC mempcpy
211
212 /* Verify that invalid offsets into an array of known size are
213 detected. */
214
215 T (char, 1, a + SR (DIFF_MIN, -1), s, n); /* { dg-warning "offset \\\[-\[0-9\]+, -1] is out of the bounds" "mempcpy" } */
216T (char, 1, a + SR (-2, -1), s, n); /* { dg-warning "offset \\\[-2, -1] is out of the bounds" "mempcpy" } */
217 T (char, 1, a + SR (-2, 0), s, n);
218
219 T (char, 1, a + UR (0, 1), s, n);
220 T (char, 1, a + UR (0, 2), s, n);
221 T (char, 1, a + UR (1, 2), s, n);
222 T (char, 1, a + UR (2, 3), s, n); /* { dg-warning "offset \\\[2, 3] is out of the bounds \\\[0, 1] of object " "mempcpy" } */
223 T (char, 1, a + UR (2, DIFF_MAX), s, n); /* { dg-warning "offset \\\[2, \[0-9\]+] is out of the bounds \\\[0, 1] of object" "mempcpy" } */
224
225 /* Offsets in excess of DIFF_MAX are treated as negative even if
226 they appear as large positive in the source. It would be nice
227 if they retained their type but unfortunately that's not how
228 it works so be prepared for both in case it ever gets fixed. */
5e27f0d5 229 T (char, 1, a + UR (3, SIZE_MAX), s, n); /* { dg-warning "offset \\\[3, -?\[0-9\]+] is out of the bounds \\\[0, 1] of object " "mempcpy" } */
cc8bea0a
MS
230
231 /* Verify that invalid offsets into an array of unknown size are
232 detected. */
233 extern char arr[];
234 T (char, 1, arr + SR (DIFF_MIN, 0), s, n);
235 T (char, 1, arr + SR (DIFF_MIN, -1), s, n); /* { dg-warning "offset \\\[-\[0-9\]+, -1] is out of the bounds of object" "mempcpy" } */
236 T (char, 1, arr + SR (DIFF_MIN, 1), s, n);
237 T (char, 1, arr + SR (DIFF_MIN, DIFF_MAX), s, n);
238 T (char, 1, arr + SR ( -2, -1), s, n); /* { dg-warning "offset \\\[-2, -1] is out of the bounds of object" "mempcpy" } */
239 T (char, 1, arr + SR ( -1, 0), s, n);
240 T (char, 1, arr + SR ( -1, 1), s, n);
241 T (char, 1, arr + SR ( -1, DIFF_MAX), s, n);
242 T (char, 1, arr + SR ( 0, 1), s, n);
243 T (char, 1, arr + SR ( 0, DIFF_MAX), s, n);
244 T (char, 1, arr + SR ( 1, 2), s, n);
245 T (char, 1, arr + SR ( 1, DIFF_MAX), s, n);
246
247 /* Verify that all offsets via a pointer to an uknown object are
248 accepted. */
249
250 /* Negative indices between [DIFF_MIN, DIFF_MAX] are valid since
251 the pointer to which the offset is applied can be at a positive
252 offset from the beginning of an object. */
253 T (char, 1, d + SR (DIFF_MIN, 0), s, n);
254 T (char, 1, d + SR (DIFF_MIN, -1), s, n);
255 T (char, 1, d + SR (DIFF_MIN, 1), s, n);
256 T (char, 1, d + SR (DIFF_MIN, DIFF_MAX), s, n);
257 T (char, 1, d + SR ( -2, -1), s, n);
258 T (char, 1, d + SR ( -1, 0), s, n);
259 T (char, 1, d + SR ( -1, 1), s, n);
260 T (char, 1, d + SR ( -1, DIFF_MAX), s, n);
261 T (char, 1, d + SR ( 0, 1), s, n);
262 T (char, 1, d + SR ( 0, DIFF_MAX), s, n);
263 T (char, 1, d + SR ( 1, 2), s, n);
264 T (char, 1, d + SR ( 1, DIFF_MAX), s, n);
265}
266
267#define TI(type, N, init, dst, src) do { \
268 type UNIQUE_NAME (a)[N] = init; \
269 type *a = UNIQUE_NAME (a); \
270 type *pd = (dst); \
271 const type *ps = (src); \
272 FUNC (pd, ps); \
273 sink (a, pd, ps, s); \
274 } while (0)
275
276void test_strcpy_bounds (char *d, const char *s)
277{
278#undef FUNC
279#define FUNC strcpy
280
281 ptrdiff_t i;
282
283 TI (char, 1, "", a, a + SR (DIFF_MIN, 0));
284 TI (char, 1, "", a, a + SR (-1, 0));
285 TI (char, 1, "", a, a + SR (-1, 1));
286 TI (char, 1, "", a, a + SR (0, 1));
287 TI (char, 1, "", a, a + SR (0, DIFF_MAX - 1));
288 TI (char, 2, "0", a, a + SR (0, DIFF_MAX - 1));
289 TI (char, 2, "0", a, a + SR (1, DIFF_MAX - 1));
3942060c
MS
290 /* The warning below isn't the most accurate because while reading
291 from it is invalid, the offset that refers just past the end of
292 the source array is strictly valid. */
293 TI (char, 2, "0", a, a + SR (2, DIFF_MAX - 1)); /* { dg-warning "offset 2 is out of the bounds \\\[0, 2] of object \[^\n\r\]+ with type 'char ?\\\[2]'" } */
cc8bea0a
MS
294 TI (char, 2, "0", a, a + SR (3, DIFF_MAX - 1)); /* { dg-warning "offset \\\[3, \[0-9\]+] is out of the bounds \\\[0, 2] of object \[^\n\r\]+ with type .char ?\\\[2\\\]." "strcpy" } */
295
296 TI (char, 3, "01", a, a + SR (0, DIFF_MAX - 1));
297 TI (char, 3, "01", a, a + SR (1, DIFF_MAX - 1));
298 TI (char, 3, "01", a, a + SR (2, DIFF_MAX - 1));
3942060c 299 TI (char, 3, "01", a, a + SR (3, DIFF_MAX - 1)); /* { dg-warning "offset 3 is out of the bounds \\\[0, 3] of object \[^\n\r\]+ with type 'char ?\\\[3]'" } */
cc8bea0a
MS
300 TI (char, 3, "01", a, a + SR (4, DIFF_MAX - 1)); /* { dg-warning "offset \\\[4, \[0-9\]+] is out of the bounds \\\[0, 3] of object \[^\n\r\]+ with type .char ?\\\[3\\\]." "strcpy" } */
301
302 TI (char, 4, "012", a, a + SR (DIFF_MAX - 2, DIFF_MAX - 1)); /* { dg-warning "offset \\\[\[0-9\]+, \[0-9\]+] is out of the bounds \\\[0, 4] of object \[^\n\r\]+ with type .char ?\\\[4\\\]." "strcpy" } */
303
304
305 TI (char, 1, "", a + SR (DIFF_MIN, 0), s);
306 TI (char, 1, "", a + SR (-1, 0), s);
307 TI (char, 1, "", a + SR (-1, 1), s);
308 TI (char, 1, "", a + SR (0, 1), s);
309 TI (char, 1, "", a + SR (0, DIFF_MAX - 1), s);
310 TI (char, 2, "", a + SR (0, DIFF_MAX - 1), s);
311 TI (char, 2, "", a + SR (1, DIFF_MAX - 1), s);
312 /* The following is diagnosed not because the initial source offset
313 it out of bounds (it isn't) but because the final source offset
314 after the access has completed, is. It would be clearer if
315 the warning mentioned the final offset. */
6889a3ac 316 TI (char, 2, "", a + SR (2, DIFF_MAX - 1), s); /* { dg-warning "offset 2 is out of the bounds \\\[0, 2] of object \[^\n\r\]+ with type .char ?\\\[2\\\]." "strcpy" } */
cc8bea0a
MS
317 TI (char, 2, "", a + SR (3, DIFF_MAX - 1), s); /* { dg-warning "offset \\\[3, \[0-9\]+] is out of the bounds \\\[0, 2] of object \[^\n\r\]+ with type .char ?\\\[2\\\]." "strcpy" } */
318
319 TI (char, 3, "", a + SR (0, DIFF_MAX - 1), s);
320 TI (char, 3, "", a + SR (1, DIFF_MAX - 1), s);
321 TI (char, 3, "", a + SR (2, DIFF_MAX - 1), s);
6889a3ac 322 TI (char, 3, "", a + SR (3, DIFF_MAX - 1), s); /* { dg-warning "offset 3 is out of the bounds \\\[0, 3] of object \[^\n\r\]+ with type .char ?\\\[3\\\]." "strcpy" } */
cc8bea0a
MS
323 TI (char, 3, "", a + SR (4, DIFF_MAX - 1), s); /* { dg-warning "offset \\\[4, \[0-9\]+] is out of the bounds \\\[0, 3] of object \[^\n\r\]+ with type .char ?\\\[3\\\]." "strcpy" } */
324
325 TI (char, 4, "", a + SR (DIFF_MAX - 2, DIFF_MAX - 1), s); /* { dg-warning "offset \\\[\[0-9\]+, \[0-9\]+] is out of the bounds \\\[0, 4] of object \[^\n\r\]+ with type .char ?\\\[4\\\]." "strcpy" } */
326}
327
328struct MA
329{
50e99db3
JL
330#if __SIZEOF_INT__ == 2
331 long i;
332#else
cc8bea0a 333 int i;
50e99db3 334#endif
cc8bea0a
MS
335 char a5[5];
336 char a11[11];
337};
338
339struct MA2
340{
341 struct MA ma3[3];
342 struct MA ma5[5];
343 char ax[];
344};
345
346struct MA3
347{
348 struct MA2 ma5[3];
349 struct MA2 ma7[7];
350};
351
352void test_strcpy_bounds_memarray_range (void)
353{
354#undef TM
355#define TM(mem, init, dst, src) \
356 do { \
357 struct MA ma; \
358 strcpy (ma.mem, init); \
359 strcpy (dst, src); \
360 sink (&ma); \
361 } while (0)
362
363 ptrdiff_t i = SR (1, 2);
364
365 TM (a5, "0", ma.a5 + i, ma.a5);
366 TM (a5, "01", ma.a5 + i, ma.a5);
367 TM (a5, "012", ma.a5 + i, ma.a5);
6889a3ac 368 TM (a5, "0123", ma.a5 + i, ma.a5); /* { dg-warning "offset 9 from the object at .ma. is out of the bounds of referenced subobject .\(MA::\)?a5. with type .char ?\\\[5]. at offset 4" "strcpy" } */
cc8bea0a
MS
369
370 TM (a11, "0", ma.a5, ma.a11);
371 TM (a11, "01", ma.a5, ma.a11);
372 TM (a11, "012", ma.a5, ma.a11);
373 TM (a11, "0123", ma.a5, ma.a11);
6889a3ac
MS
374 TM (a11, "01234", ma.a5, ma.a11); /* { dg-warning "offset 9 from the object at .ma. is out of the bounds of referenced subobject .\(MA::\)?a5. with type .char ?\\\[5]' at offset 4" } */
375 TM (a11, "012345", ma.a5, ma.a11); /* { dg-warning "offset \\\[9, 10] from the object at .ma. is out of the bounds of referenced subobject .\(MA::\)?a5. with type .char ?\\\[5]' at offset 4" } */
376 TM (a11, "0123456", ma.a5, ma.a11); /* { dg-warning "offset \\\[9, 11] from the object at .ma. is out of the bounds of referenced subobject .\(MA::\)?a5. with type .char ?\\\[5]' at offset 4" } */
cc8bea0a
MS
377
378 TM (a11, "0123456", ma.a11 + i, "789abcd");
379}
380
381void test_strcpy_bounds_memarray_var (struct MA *pma,
382 struct MA2 *pma2,
383 struct MA3 *pma3,
384 const char *s, size_t n)
385{
386#undef TM
387#define TM(dst, src) do { \
388 strcpy (dst, src); \
389 sink (dst, src); \
390 } while (0)
391
392 TM (pma->a5, s);
393 TM (pma->a5 + 0, s);
394 TM (pma->a5 + 1, s);
395 TM (pma->a5 + 4, s);
396
397 /* The following forms a pointer during the call that's outside
398 the bounds of the array it was derived from (pma->a5) so
399 it should be diagnosed but the representation of the pointer
400 addition doesn't contain information to distinguish it from
401 the valid pma->a11 + 1 so this is an XFAIL. */
402 TM (pma->a5 + 5, s); /* { dg-warning "offset 17 from the object at .pma. is out of the bounds of .struct MA." "strcpy" { xfail *-*-* } } */
403
404 /* The following also forms an out-of-bounds pointer but similar
405 to the above, there is no reliable way to distinguish it from
406 (char*)&pma[1].i + 1 so this too is not diagnosed. */
407 TM (pma->a5 + sizeof *pma + 1, s); /* { dg-warning "offset 17 from the object at .pma. is out of the bounds of .struct MA." "strcpy" { xfail *-*-* } } */
408
409 TM (pma->a5 - 1, s); /* { dg-warning "offset -1 from the object at .pma. is out of the bounds of .struct MA." "strcpy" { xfail *-*-* } } */
410
411 TM (pma[1].a5, s);
412 TM (pma[2].a5 + 0, s);
413 TM (pma[3].a5 + 1, s);
414 TM (pma[4].a5 + 4, s);
415
416
417 extern struct MA3 ma3[3];
418 TM (ma3[0].ma5[0].ma3[0].a5 + 6, s);
419}