1 /* Test for MIN and MAX expressions involving pointers.
2 { dg-do compile }
3 { dg-options "-O2 -Wall -Wno-array-bounds -ftrack-macro-expansion=0" } */
4
5 #include "range.h"
6
7 #define INT_MAX __INT_MAX__
8
9 #define MIN(x, y) ((x) < (y) ? (x) : (y))
10 #define MAX(x, y) ((x) < (y) ? (y) : (x))
11
12 typedef __SIZE_TYPE__ size_t;
13
14 void* memset (void*, int, size_t);
15 #define memset(...) sink (memset (__VA_ARGS__))
16
17 void sink (void*, ...);
18
19 volatile int cond, vi;
20 char* volatile ptr;
21
test_min(void)22 void test_min (void)
23 {
24 const int i1 = SR (1, INT_MAX);
25 const int i2 = SR (2, INT_MAX);
26
27 {
28 /* Exercise both pointers pointing to a different unknown object plus
29 positive constant offset. Since PTR is volatile P1 and P2 cannot
30 normally be considered to point to the same object. It can only
31 be inferred from the MIN expression. */
32 char *p1 = ptr + 1;
33 char *p2 = ptr + 2;
34
35 char *q = MIN (p1, p2);
36
37 memset (q, 0, 1);
38 memset (q, 0, 2);
39 memset (q, 0, INT_MAX);
40 // { dg-warning "writing 2147483647 bytes into a region of size 2147483646" "ilp32" { target ilp32 } .-1 }
41 memset (q, 0, DIFF_MAX - 2);
42 memset (q, 0, DIFF_MAX);
43 // { dg-warning "writing 2147483647 bytes into a region of size 2147483646" "ilp32" { target ilp32 } .-1 }
44 // { dg-warning "writing 9223372036854775807 bytes into a region of size 9223372036854775806" "lp64" { target lp64 } .-2 }
45 }
46
47 {
48 /* Exercise both pointers pointing to a different unknown object plus
49 variable offset. */
50 char *p1 = ptr + vi;
51 char *p2 = ptr + vi;
52
53 char *q = MIN (p1, p2);
54
55 memset (q, 0, 1);
56 memset (q, 0, 2);
57 memset (q, 0, INT_MAX);
58 }
59
60 {
61 /* Exercise both pointers pointing to the same object plus constant
62 offset. */
63 char a2[2]; // { dg-message "at offset 1 into destination object 'a2' of size 2" "note" }
64 char *p1 = a2 + 1;
65 char *p2 = a2 + 2;
66
67 char *q = MIN (p1, p2);
68
69 memset (q, 0, 1);
70 memset (q, 0, 2); // { dg-warning "writing 2 bytes into a region of size 1 " }
71 }
72
73 {
74 /* Exercise both pointers pointing to the same object plus offset
75 in a known range. */
76 char a3[3]; // { dg-message "at offset \\\[1, 3] into destination object 'a3'" "note" }
77 char *pi = a3 + i1;
78 char *pj = a3 + i2;
79
80 char *q = MIN (pi, pj);
81
82 memset (q, 0, 1);
83 memset (q, 0, 2);
84 memset (q, 0, 3); // { dg-warning "writing 3 bytes into a region of size 2 " }
85 }
86
87 {
88 /* Exercise both pointers pointing to the same object plus variable
89 offset. Verify that no offset is mentioned in the note (since
90 its unknown, printing its full range is unnecessary). */
91 char a4[4]; // { dg-message ": destination object 'a4'" "note" }
92 char *pi = a4 + vi;
93 char *pj = a4 + vi;
94
95 char *q = MIN (pi, pj);
96
97 memset (q, 0, 1);
98 memset (q, 0, 2);
99 memset (q, 0, 3);
100 memset (q, 0, 4);
101 memset (q, 0, 5); // { dg-warning "writing 5 bytes into a region of size 4 " }
102 }
103
104 {
105 /* Exercise a pointer pointing to a known object with one pointing
106 to an unknown object. */
107 char a5[5]; // { dg-message ": destination object 'a5'" "note" }
108 char *p = ptr;
109 char *q = MIN (p, a5);
110
111 memset (q, 0, 1);
112 memset (q, 0, 2);
113 memset (q, 0, 5);
114 memset (q, 0, 6); // { dg-warning "writing 6 bytes into a region of size 5 " }
115 }
116
117 {
118 /* Exercise a pointer pointing to a known object plus constant offset
119 with one pointing to an unknown object. */
120 char a6[6]; // { dg-message ": destination object 'a6'" "note" }
121 char *p1 = ptr;
122 char *p2 = a6 + 1;
123 char *q = MIN (p1, p2);
124
125 memset (q, 0, 1);
126 memset (q, 0, 2);
127 memset (q, 0, 6);
128 memset (q, 0, 7); // { dg-warning "writing 7 bytes into a region of size 6 " }
129 }
130
131 {
132 /* Exercise a pointer pointing to a known object with one pointing
133 to an unknown object plus constant offset. */
134 char a7[7]; // { dg-message ": destination object 'a7'" "note" }
135 char *p1 = a7;
136 char *p2 = ptr + 1;
137 /* Since p1 points to a7[0] it must be less than any pointer to a7
138 plus positive offset, and so Q == P1. */
139 char *q = MIN (p1, p2);
140
141 memset (q, 0, 1);
142 memset (q, 0, 2);
143 memset (q, 0, 3);
144 memset (q, 0, 7);
145 memset (q, 0, 8); // { dg-warning "writing 8 bytes into a region of size 7 " }
146 }
147
148 {
149 /* Exercise a pointer pointing to a known object plus constant offset
150 with one pointing to an unknown object plus a different constant
151 offset. */
152 char a8[8]; // { dg-message "at offset 1 into destination object 'a8'" "note" }
153 char *p1 = a8 + 1;
154 char *p2 = ptr + 2;
155 /* Since P1 points to A8[1] it must be less than or equal to any
156 pointer to A8 plus positive offset. Either way, Q must point
157 to A8[1]. */
158 char *q = MIN (p1, p2);
159
160 memset (q, 0, 1);
161 memset (q, 0, 2);
162 memset (q, 0, 7);
163 memset (q, 0, 8); // { dg-warning "writing 8 bytes into a region of size 7 " }
164 }
165
166 {
167 /* Same as above but with larger offsets. */
168 char a9[9]; // { dg-message "at offset 3 into destination object 'a9'" "note" }
169 char *p1 = a9 + 3;
170 char *p2 = ptr + 4;
171 /* Since P1 points to A9[3] it must be less than or equal to any
172 pointer anywhere into A9 plus 4, so Q must point to A9[3]. */
173 char *q = MIN (p1, p2);
174
175 memset (q, 0, 1);
176 memset (q, 0, 2);
177 memset (q, 0, 6);
178 memset (q, 0, 7); // { dg-warning "writing 7 bytes into a region of size 6 " }
179 }
180
181 {
182 /* Same as above but with the offsets reversed. */
183 char a10[10]; // { dg-message "at offset 5 into destination object 'a10'" "note" }
184 char *p1 = a10 + 10;
185 char *p2 = ptr + 5;
186 /* Since P1 points just past the end of A10 it could be either less
187 or equal to another pointer anywhere into A10 plus 3 because
188 the other pointer itself could start at a non-zero offset that's
189 not reflected in the determined offset). */
190 char *q = MIN (p1, p2);
191
192 memset (q, 0, 1);
193 memset (q, 0, 2);
194 memset (q, 0, 5);
195 memset (q, 0, 6); // { dg-warning "writing 6 bytes into a region of size 5 " }
196 }
197
198 {
199 char a3[3]; // { dg-message ": destination object 'a3'" "note" }
200 char *p1 = ptr;
201 char *p2 = a3 + i1;
202 char *q = MIN (p1, p2);
203
204 memset (q, 0, 1);
205 memset (q, 0, 2);
206 memset (q, 0, 3);
207 memset (q, 0, 4); // { dg-warning "writing 4 bytes into a region of size 3 " }
208 }
209 }
210
211
test_max(void)212 void test_max (void)
213 {
214 const int i1 = SR (1, INT_MAX);
215 const int i2 = SR (2, INT_MAX);
216
217 {
218 /* Exercise both pointers pointing to the same object plus constant
219 offset. */
220 char a2[2]; // { dg-message "at offset 1 into destination object 'a2' of size 2" "note" }
221 char *pi = a2 + 1;
222 char *pj = a2 + 2;
223
224 char *q = MAX (pi, pj);
225
226 memset (q, 0, 1);
227 memset (q, 0, 2); // { dg-warning "writing 2 bytes into a region of size 1 " }
228 }
229
230 {
231 /* Exercise both pointers pointing to the same object plus offset
232 in a known range. */
233 char a3[3]; // { dg-message "at offset \\\[1, 3] into destination object 'a3'" "note" }
234 char *pi = a3 + i1;
235 char *pj = a3 + i2;
236
237 char *q = MAX (pi, pj);
238
239 memset (q, 0, 1);
240 memset (q, 0, 2);
241 memset (q, 0, 3); // { dg-warning "writing 3 bytes into a region of size 2 " }
242 }
243
244 {
245 /* Exercise both pointers pointing to the same object plus variable
246 offset. Verify that no offset is mentioned in the note (since
247 its unknown, printing its full range is unnecessary). */
248 char a4[4]; // { dg-message ": destination object 'a4'" "note" }
249 char *pi = a4 + vi;
250 char *pj = a4 + vi;
251
252 char *q = MAX (pi, pj);
253
254 memset (q, 0, 1);
255 memset (q, 0, 2);
256 memset (q, 0, 3);
257 memset (q, 0, 4);
258 memset (q, 0, 5); // { dg-warning "writing 5 bytes into a region of size 4 " }
259 }
260
261 {
262 /* Exercise a pointer pointing to a known object with one pointing
263 to an unknown object. */
264 char a5[5]; // { dg-message ": destination object 'a5'" "note" }
265 char *p = ptr;
266 char *q = MAX (p, a5);
267
268 memset (q, 0, 1);
269 memset (q, 0, 2);
270 memset (q, 0, 5);
271 memset (q, 0, 6); // { dg-warning "writing 6 bytes into a region of size 5 " }
272 }
273
274 {
275 /* Exercise a pointer pointing to a known object plus constant offset
276 with one pointing to an unknown object. */
277 char a6[6]; // { dg-message "at offset 1 into destination object 'a6'" "note" }
278 char *p1 = ptr;
279 char *p2 = a6 + 1;
280 char *q = MAX (p1, p2);
281
282 memset (q, 0, 1);
283 memset (q, 0, 5);
284 memset (q, 0, 6); // { dg-warning "writing 6 bytes into a region of size 5 " }
285 memset (q, 0, 7); // { dg-warning "writing 7 bytes into a region of size 5 " }
286 }
287
288 {
289 /* Exercise a pointer pointing to a known object with one pointing
290 to an unknown object plus constant offset. */
291 char a7[7]; // { dg-message "at offset 1 into destination object 'a7'" "note" }
292 char *p1 = a7;
293 char *p2 = ptr + 1;
294 /* Since p1 points to a7[0] it must be less than any pointer to a7
295 plus positive offset, and so Q == P2. */
296 char *q = MAX (p1, p2);
297
298 memset (q, 0, 1);
299 memset (q, 0, 6);
300 memset (q, 0, 7); // { dg-warning "writing 7 bytes into a region of size 6 " }
301 memset (q, 0, 8); // { dg-warning "writing 8 bytes into a region of size 6 " }
302 }
303
304 {
305 /* Exercise a pointer pointing to a known object plus constant offset
306 with one pointing to an unknown object plus a different constant
307 offset. */
308 char a8[8]; // { dg-message "at offset 2 into destination object 'a8'" "note" }
309 char *p1 = a8 + 1;
310 char *p2 = ptr + 2;
311 /* Since P1 points to A8[1] it must be less than or equal to any
312 pointer to A8 plus positive offset. Either way, Q must point
313 to A8[2]. */
314 char *q = MAX (p1, p2);
315
316 memset (q, 0, 1);
317 memset (q, 0, 6);
318 memset (q, 0, 7); // { dg-warning "writing 7 bytes into a region of size 6 " }
319 memset (q, 0, 8); // { dg-warning "writing 8 bytes into a region of size 6 " }
320 }
321
322 {
323 /* Same as above but with larger offsets. */
324 char a9[9]; // { dg-message "at offset 4 into destination object 'a9'" "note" }
325 char *p1 = a9 + 3;
326 char *p2 = ptr + 4;
327 /* Since P1 points to A9[3] it must be less than or equal to any
328 pointer anywhere into A9 plus 4, so Q must point to A9[4]. */
329 char *q = MAX (p1, p2);
330
331 memset (q, 0, 1);
332 memset (q, 0, 2);
333 memset (q, 0, 5);
334 memset (q, 0, 6); // { dg-warning "writing 6 bytes into a region of size 5 " }
335 }
336
337 {
338 /* Same as above but with the offsets reversed. */
339 char a10[10]; // { dg-message "at offset 10 into destination object 'a10'" "note" }
340 char *p1 = a10 + 10;
341 char *p2 = ptr + 5;
342 /* Since P1 points just past the end of A10 it could be either less
343 or equal to another pointer anywhere into A10 plus 3 because
344 the other pointer itself could start at a non-zero offset that's
345 not reflected in the determaxed offset). */
346 char *q = MAX (p1, p2);
347
348 memset (q, 0, 1); // { dg-warning "writing 1 byte into a region of size 0 " }
349 }
350
351 {
352 char a11[11]; // { dg-message "at offset \\\[1, 11] into destination object 'a11'" "note" }
353 char *p1 = ptr;
354 char *p2 = a11 + i1;
355 char *q = MAX (p1, p2);
356
357 memset (q, 0, 1);
358 memset (q, 0, 2);
359 memset (q, 0, 10);
360 memset (q, 0, 11); // { dg-warning "writing 11 bytes into a region of size 10 " }
361 }
362 }
363
364