]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/testsuite/gcc.dg/strlenopt-40.c
Update copyright years.
[thirdparty/gcc.git] / gcc / testsuite / gcc.dg / strlenopt-40.c
CommitLineData
c42d0aa0
MS
1/* PR tree-optimization/83671 - fix for false positive reported by
2 -Wstringop-overflow does not work with inlining
3 { dg-do compile }
c32f7df9 4 { dg-options "-O1 -fdump-tree-optimized" } */
c42d0aa0
MS
5
6#include "strlenopt.h"
7
8#define DIFF_MAX __PTRDIFF_MAX__
9
10#define CAT(x, y) x ## y
11#define CONCAT(x, y) CAT (x, y)
12#define FAILNAME(name) CONCAT (call_ ## name ##_on_line_, __LINE__)
13
14#define FAIL(name) do { \
15 extern void FAILNAME (name) (void); \
16 FAILNAME (name)(); \
17 } while (0)
18
19/* Macros to emit a call to funcation named
20 call_in_{true,false}_branch_not_eliminated_on_line_NNN()
21 for each call that's expected to be eliminated. The dg-final
22 scan-tree-dump-time directive at the bottom of the test verifies
23 that no such call appears in output. */
24#define ELIM_TRUE(expr) \
25 if (!(expr)) FAIL (in_true_branch_not_eliminated); else (void)0
26
27#define ELIM_FALSE(expr) \
28 if (!!(expr)) FAIL (in_false_branch_not_eliminated); else (void)0
29
30/* Macro to emit a call to a function named
31 call_made_in_{true,false}_branch_on_line_NNN()
32 for each call that's expected to be retained. The dg-final
33 scan-tree-dump-time directive at the bottom of the test verifies
34 that the expected number of both kinds of calls appears in output
35 (a pair for each line with the invocation of the KEEP() macro. */
36#define KEEP(expr) \
37 if (expr) \
38 FAIL (made_in_true_branch); \
39 else \
40 FAIL (made_in_false_branch)
41
42typedef char A3[3], A5[5], A7[7], AX[];
43
44typedef A3 A7_3[7];
45typedef A3 AX_3[];
46typedef A5 A7_5[7];
47typedef A7 A5_7[5];
48
49extern A7_3 a7_3;
50extern A5_7 a5_7;
51extern AX_3 ax_3;
52
53extern A3 a3;
54extern A7 a5;
55extern A7 a7;
56extern AX ax;
57
58extern A3 *pa3;
59extern A5 *pa5;
60extern A7 *pa7;
61
62extern A7_3 *pa7_3;
63extern AX_3 *pax_3;
64extern A5_7 *pa5_7;
65extern A7_5 *pa7_5;
66
67extern char *ptr;
68
69struct MemArrays0 {
70 A7_3 a7_3;
71 A5_7 a5_7;
72 char a3[3], a5[5], a0[0];
73};
74struct MemArraysX { char a3[3], a5[5], ax[]; };
75struct MemArrays7 { char a3[3], a5[5], a7[7]; };
76
77struct MemArrays0 ma0_3_5_7[3][5][7];
78
79void elim_strings (int i)
80{
81 ELIM_TRUE (strlen (i < 0 ? "123" : "321") == 3);
82 ELIM_FALSE (strlen (i < 0 ? "123" : "321") > 3);
83 ELIM_FALSE (strlen (i < 0 ? "123" : "321") < 3);
84
85 ELIM_TRUE (strlen (i < 0 ? "123" : "4321") >= 3);
86 ELIM_FALSE (strlen (i < 0 ? "123" : "4321") > 4);
87 ELIM_FALSE (strlen (i < 0 ? "123" : "4321") < 3);
88
89 ELIM_TRUE (strlen (i < 0 ? "1234" : "321") >= 3);
90 ELIM_FALSE (strlen (i < 0 ? "1234" : "321") < 3);
91 ELIM_FALSE (strlen (i < 0 ? "1234" : "321") > 4);
92
93 ELIM_TRUE (strlen (i < 0 ? "123" : "4321") <= 4);
94 ELIM_TRUE (strlen (i < 0 ? "1234" : "321") <= 4);
95
96 ELIM_TRUE (strlen (i < 0 ? "1" : "123456789") <= 9);
97 ELIM_TRUE (strlen (i < 0 ? "1" : "123456789") >= 1);
98}
99
100/* Verify that strlen calls involving uninitialized global arrays
101 of known size are eliminated when they appear in expressions
102 that test for results that must be true. */
103void elim_global_arrays (int i)
104{
105 /* Verify that the expression involving the strlen call as well
106 as whatever depends on it is eliminated from the test output.
107 All these expressions must be trivially true. */
eef2da67
MS
108 ELIM_TRUE (strlen (a7_3[0]) < sizeof a7_3);
109 ELIM_TRUE (strlen (a7_3[1]) < sizeof a7_3 - sizeof *a7_3);
110 ELIM_TRUE (strlen (a7_3[6]) < sizeof a7_3 - 5 * sizeof *a7_3);
111 ELIM_TRUE (strlen (a7_3[i]) < sizeof a7_3);
112
113 ELIM_TRUE (strlen (a5_7[0]) < sizeof a5_7);
114 ELIM_TRUE (strlen (a5_7[1]) < sizeof a5_7 - sizeof *a5_7);
115 ELIM_TRUE (strlen (a5_7[4]) < sizeof a5_7 - 3 * sizeof *a5_7);
116 ELIM_TRUE (strlen (a5_7[i]) < sizeof a5_7);
117
118 /* Even when treating a multi-dimensional array as a single string
119 the length must be less DIFF_MAX - (ax_3[i] - ax_3[0]) but GCC
120 doesn't do that computation yet so avoid testing it. */
121 ELIM_TRUE (strlen (ax_3[0]) < DIFF_MAX);
122 ELIM_TRUE (strlen (ax_3[1]) < DIFF_MAX);
123 ELIM_TRUE (strlen (ax_3[9]) < DIFF_MAX);
124 ELIM_TRUE (strlen (ax_3[i]) < DIFF_MAX);
c42d0aa0
MS
125
126 ELIM_TRUE (strlen (a3) < sizeof a3);
127 ELIM_TRUE (strlen (a7) < sizeof a7);
128
129 ELIM_TRUE (strlen (ax) != DIFF_MAX);
5d6655eb
MS
130 /* ELIM_TRUE (strlen (ax) != DIFF_MAX - 1); */
131 /* ELIM_TRUE (strlen (ax) < DIFF_MAX - 1); */
c42d0aa0
MS
132}
133
134void elim_pointer_to_arrays (void)
135{
eef2da67
MS
136 /* Unfortunately, GCC cannot be trusted not to misuse a pointer
137 to a smaller array to point to an object of a bigger type so
138 the strlen range optimization must assume each array pointer
139 points effectively to an array of an unknown bound. */
140 ELIM_TRUE (strlen (*pa7) < DIFF_MAX);
141 ELIM_TRUE (strlen (*pa5) < DIFF_MAX);
142 ELIM_TRUE (strlen (*pa3) < DIFF_MAX);
143
144 ELIM_TRUE (strlen ((*pa7_3)[0]) < DIFF_MAX);
145 ELIM_TRUE (strlen ((*pa7_3)[1]) < DIFF_MAX);
146 ELIM_TRUE (strlen ((*pa7_3)[6]) < DIFF_MAX);
147
148 ELIM_TRUE (strlen ((*pax_3)[0]) < DIFF_MAX);
149 ELIM_TRUE (strlen ((*pax_3)[1]) < DIFF_MAX);
150 ELIM_TRUE (strlen ((*pax_3)[9]) < DIFF_MAX);
151
152 ELIM_TRUE (strlen ((*pa5_7)[0]) < DIFF_MAX);
153 ELIM_TRUE (strlen ((*pa5_7)[1]) < DIFF_MAX);
154 ELIM_TRUE (strlen ((*pa5_7)[4]) < DIFF_MAX);
c42d0aa0
MS
155}
156
157void elim_global_arrays_and_strings (int i)
158{
159 ELIM_TRUE (strlen (i < 0 ? a3 : "") < 3);
160 ELIM_TRUE (strlen (i < 0 ? a3 : "1") < 3);
161 ELIM_TRUE (strlen (i < 0 ? a3 : "12") < 3);
162 ELIM_TRUE (strlen (i < 0 ? a3 : "123") < 4);
163
164 ELIM_FALSE (strlen (i < 0 ? a3 : "") > 3);
165 ELIM_FALSE (strlen (i < 0 ? a3 : "1") > 3);
166 ELIM_FALSE (strlen (i < 0 ? a3 : "12") > 3);
167 ELIM_FALSE (strlen (i < 0 ? a3 : "123") > 4);
168
169 ELIM_TRUE (strlen (i < 0 ? a7 : "") < 7);
170 ELIM_TRUE (strlen (i < 0 ? a7 : "1") < 7);
171 ELIM_TRUE (strlen (i < 0 ? a7 : "12") < 7);
172 ELIM_TRUE (strlen (i < 0 ? a7 : "123") < 7);
173 ELIM_TRUE (strlen (i < 0 ? a7 : "123456") < 7);
174 ELIM_TRUE (strlen (i < 0 ? a7 : "1234567") < 8);
175
176 ELIM_FALSE (strlen (i < 0 ? a7 : "") > 6);
177 ELIM_FALSE (strlen (i < 0 ? a7 : "1") > 6);
178 ELIM_FALSE (strlen (i < 0 ? a7 : "12") > 6);
179 ELIM_FALSE (strlen (i < 0 ? a7 : "123") > 6);
180 ELIM_FALSE (strlen (i < 0 ? a7 : "123456") > 7);
181 ELIM_FALSE (strlen (i < 0 ? a7 : "1234567") > 8);
182}
183
184void elim_member_arrays_obj (int i)
185{
eef2da67
MS
186 ELIM_TRUE (strlen (ma0_3_5_7[0][0][0].a3) < sizeof ma0_3_5_7);
187 ELIM_TRUE (strlen (ma0_3_5_7[0][0][1].a3) < sizeof ma0_3_5_7);
188 ELIM_TRUE (strlen (ma0_3_5_7[0][0][2].a3) < sizeof ma0_3_5_7);
189 ELIM_TRUE (strlen (ma0_3_5_7[0][0][6].a3) < sizeof ma0_3_5_7);
c42d0aa0 190
eef2da67
MS
191 ELIM_TRUE (strlen (ma0_3_5_7[1][0][0].a3) < sizeof ma0_3_5_7);
192 ELIM_TRUE (strlen (ma0_3_5_7[2][0][1].a3) < sizeof ma0_3_5_7);
c42d0aa0 193
eef2da67
MS
194 ELIM_TRUE (strlen (ma0_3_5_7[1][1][0].a3) < sizeof ma0_3_5_7);
195 ELIM_TRUE (strlen (ma0_3_5_7[2][4][6].a3) < sizeof ma0_3_5_7);
c42d0aa0 196
eef2da67
MS
197 ELIM_TRUE (strlen (ma0_3_5_7[0][0][0].a5) < sizeof ma0_3_5_7);
198 ELIM_TRUE (strlen (ma0_3_5_7[0][0][1].a5) < sizeof ma0_3_5_7);
199 ELIM_TRUE (strlen (ma0_3_5_7[0][0][2].a5) < sizeof ma0_3_5_7);
200 ELIM_TRUE (strlen (ma0_3_5_7[0][0][6].a5) < sizeof ma0_3_5_7);
c42d0aa0 201
eef2da67
MS
202 ELIM_TRUE (strlen (ma0_3_5_7[1][0][0].a5) < sizeof ma0_3_5_7);
203 ELIM_TRUE (strlen (ma0_3_5_7[2][0][1].a5) < sizeof ma0_3_5_7);
c42d0aa0 204
eef2da67
MS
205 ELIM_TRUE (strlen (ma0_3_5_7[1][1][0].a5) < sizeof ma0_3_5_7);
206 ELIM_TRUE (strlen (ma0_3_5_7[2][4][6].a5) < sizeof ma0_3_5_7);
c42d0aa0 207
eef2da67
MS
208 ELIM_TRUE (strlen (ma0_3_5_7[0][0][0].a7_3[0]) < sizeof ma0_3_5_7);
209 ELIM_TRUE (strlen (ma0_3_5_7[2][4][6].a7_3[2]) < sizeof ma0_3_5_7);
c42d0aa0 210
eef2da67
MS
211 ELIM_TRUE (strlen (ma0_3_5_7[0][0][0].a5_7[0]) < sizeof ma0_3_5_7);
212 ELIM_TRUE (strlen (ma0_3_5_7[2][4][6].a5_7[4]) < sizeof ma0_3_5_7);
c42d0aa0
MS
213}
214
215
216#line 1000
217
218/* Verify that strlen calls involving uninitialized global arrays
219 of unknown size are not eliminated when they appear in expressions
220 that test for results that need not be true. */
221void keep_global_arrays (int i)
222{
223 KEEP (strlen (a7_3[0]) < 2);
224 KEEP (strlen (a7_3[1]) < 2);
225 KEEP (strlen (a7_3[6]) < 2);
226 KEEP (strlen (a7_3[i]) < 2);
227
228 KEEP (strlen (a5_7[0]) < 6);
229 KEEP (strlen (a5_7[1]) < 6);
230 KEEP (strlen (a5_7[4]) < 6);
231 KEEP (strlen (a5_7[i]) < 6);
232
eef2da67
MS
233 /* Verify also that tests (and strlen calls) are not eliminated
234 for results greater than what would the size of the innermost
235 array suggest might be possible (in case the element array is
236 not nul-terminated), even though such calls are undefined. */
237 KEEP (strlen (a5_7[0]) > sizeof a5_7 - 2);
238 KEEP (strlen (a5_7[1]) > sizeof a5_7 - sizeof a5_7[1] - 2);
239 KEEP (strlen (a5_7[i]) > sizeof a5_7 - 2);
240
c42d0aa0
MS
241 KEEP (strlen (ax_3[0]) < 2);
242 KEEP (strlen (ax_3[1]) < 2);
243 KEEP (strlen (ax_3[2]) < 2);
244 KEEP (strlen (ax_3[i]) < 2);
245
eef2da67
MS
246 /* Here again, verify that the ax_3 matrix is treated essentially
247 as a flat array of unknown bound for the benefit of all the
248 undefined code out there that might rely on it. */
249 KEEP (strlen (ax_3[0]) > 3);
250 KEEP (strlen (ax_3[1]) > 9);
251 KEEP (strlen (ax_3[2]) > 99);
252 KEEP (strlen (ax_3[i]) > 999);
253
c42d0aa0
MS
254 KEEP (strlen (a3) < 2);
255 KEEP (strlen (a7) < 6);
256
257 KEEP (strlen (a3 + i) < 2);
258 KEEP (strlen (a7 + i) < 2);
259
260 /* The length of an array of unknown size may be as large as
261 DIFF_MAX - 2. */
262 KEEP (strlen (ax) != DIFF_MAX - 2);
263 KEEP (strlen (ax) < DIFF_MAX - 2);
264 KEEP (strlen (ax) < 999);
265 KEEP (strlen (ax) < 1);
266}
267
eef2da67 268void keep_pointer_to_arrays (int i)
c42d0aa0
MS
269{
270 KEEP (strlen (*pa7) < 6);
271 KEEP (strlen (*pa5) < 4);
272 KEEP (strlen (*pa3) < 2);
273
eef2da67
MS
274 /* Since GCC cannot be trusted not to misuse a pointer to a smaller
275 array to point to an object of a larger type verify that the bound
276 in a pointer to an array of a known bound isn't relied on for
277 the strlen range optimization. If GCC is fixed to avoid these
278 misuses these tests can be removed. */
279 KEEP (strlen (*pa7) > sizeof *pa7);
280 KEEP (strlen (*pa5) > sizeof *pa5);
281 KEEP (strlen (*pa3) > sizeof *pa3);
282
c42d0aa0
MS
283 KEEP (strlen ((*pa7_3)[0]) < 2);
284 KEEP (strlen ((*pa7_3)[1]) < 2);
285 KEEP (strlen ((*pa7_3)[6]) < 2);
eef2da67
MS
286 KEEP (strlen ((*pa7_3)[i]) < 2);
287
288 /* Same as above. */
289 KEEP (strlen ((*pa7_3)[0]) > sizeof *pa7_3);
290 KEEP (strlen ((*pa7_3)[i]) > sizeof *pa7_3);
c42d0aa0
MS
291
292 KEEP (strlen ((*pax_3)[0]) < 2);
293 KEEP (strlen ((*pax_3)[1]) < 2);
294 KEEP (strlen ((*pax_3)[9]) < 2);
eef2da67
MS
295 KEEP (strlen ((*pax_3)[i]) < 2);
296
297 /* Same as above. */
298 KEEP (strlen ((*pax_3)[0]) > 3);
299 KEEP (strlen ((*pax_3)[i]) > 333);
c42d0aa0
MS
300
301 KEEP (strlen ((*pa5_7)[0]) < 6);
302 KEEP (strlen ((*pa5_7)[1]) < 6);
303 KEEP (strlen ((*pa5_7)[4]) < 6);
eef2da67
MS
304 KEEP (strlen ((*pa5_7)[i]) < 6);
305
306 /* Same as above. */
307 KEEP (strlen ((*pa5_7)[0]) > sizeof *pa5_7);
308 KEEP (strlen ((*pa5_7)[i]) > sizeof *pa5_7);
309 }
c42d0aa0
MS
310
311void keep_global_arrays_and_strings (int i)
312{
313 KEEP (strlen (i < 0 ? a3 : "") < 2);
314 KEEP (strlen (i < 0 ? a3 : "1") < 2);
315 KEEP (strlen (i < 0 ? a3 : "12") < 2);
316 KEEP (strlen (i < 0 ? a3 : "123") < 3);
317
318 KEEP (strlen (i < 0 ? a7 : "") < 5);
319 KEEP (strlen (i < 0 ? a7 : "1") < 5);
320 KEEP (strlen (i < 0 ? a7 : "12") < 5);
321 KEEP (strlen (i < 0 ? a7 : "123") < 5);
322 KEEP (strlen (i < 0 ? a7 : "123456") < 6);
323 KEEP (strlen (i < 0 ? a7 : "1234567") < 6);
eef2da67
MS
324
325 /* Verify that a matrix is treated as a flat array even in a conditional
326 expression (i.e., don't assume that a7_3[0] is nul-terminated, even
327 though calling strlen() on such an array is undefined). */
328 KEEP (strlen (i < 0 ? a7_3[0] : "") > 7);
329 KEEP (strlen (i < 0 ? a7_3[i] : "") > 7);
c42d0aa0
MS
330}
331
332void keep_member_arrays_obj (int i)
333{
334 KEEP (strlen (ma0_3_5_7[0][0][0].a3) < 2);
335 KEEP (strlen (ma0_3_5_7[0][0][1].a3) < 2);
336 KEEP (strlen (ma0_3_5_7[0][0][2].a3) < 2);
337 KEEP (strlen (ma0_3_5_7[0][0][6].a3) < 2);
338
339 KEEP (strlen (ma0_3_5_7[1][0][0].a3) < 2);
340 KEEP (strlen (ma0_3_5_7[2][0][1].a3) < 2);
341
342 KEEP (strlen (ma0_3_5_7[1][1][0].a3) < 2);
343 KEEP (strlen (ma0_3_5_7[2][4][6].a3) < 2);
344
345 KEEP (strlen (ma0_3_5_7[0][0][0].a5) < 4);
346 KEEP (strlen (ma0_3_5_7[0][0][1].a5) < 4);
347 KEEP (strlen (ma0_3_5_7[0][0][2].a5) < 4);
348 KEEP (strlen (ma0_3_5_7[0][0][6].a5) < 4);
349
350 KEEP (strlen (ma0_3_5_7[1][0][0].a5) < 4);
351 KEEP (strlen (ma0_3_5_7[2][0][1].a5) < 4);
352
353 KEEP (strlen (ma0_3_5_7[1][1][0].a5) < 4);
354 KEEP (strlen (ma0_3_5_7[2][4][6].a5) < 4);
355
356 KEEP (strlen (ma0_3_5_7[0][0][0].a7_3[0]) < 2);
357 KEEP (strlen (ma0_3_5_7[2][4][6].a7_3[2]) < 2);
358
359 KEEP (strlen (ma0_3_5_7[0][0][0].a5_7[0]) < 6);
360 KEEP (strlen (ma0_3_5_7[2][4][6].a5_7[4]) < 6);
eef2da67
MS
361
362 /* Again, verify that the .a3 array isn't assumed to necessarily
363 be nul-terminated. */
364 KEEP (strlen (ma0_3_5_7[0][0][0].a3) > 2);
365 KEEP (strlen (ma0_3_5_7[0][0][6].a3) > 2);
366 KEEP (strlen (ma0_3_5_7[0][0][i].a3) > 2);
c42d0aa0
MS
367}
368
369void keep_member_arrays_ptr (struct MemArrays0 *ma0,
370 struct MemArraysX *max,
371 struct MemArrays7 *ma7,
372 int i)
373{
374 KEEP (strlen (ma0->a7_3[0]) > 0);
375 KEEP (strlen (ma0->a7_3[0]) < 2);
376 KEEP (strlen (ma0->a7_3[1]) < 2);
377 KEEP (strlen (ma0->a7_3[6]) < 2);
378 KEEP (strlen (ma0->a7_3[6]) < 2);
379 KEEP (strlen (ma0->a7_3[i]) > 0);
380 KEEP (strlen (ma0->a7_3[i]) < 2);
381 KEEP (strlen (ma0->a7_3[i]) < 2);
382
eef2da67
MS
383 /* Again, verify that the member array isn't assumed to necessarily
384 be nul-terminated. */
385 KEEP (strlen (ma0->a7_3[0]) > sizeof ma0->a7_3);
386 KEEP (strlen (ma0->a7_3[i]) > sizeof ma0->a7_3);
387
c42d0aa0
MS
388 KEEP (strlen (ma0->a5_7[0]) < 5);
389 KEEP (strlen (ma0[0].a5_7[0]) < 5);
390 KEEP (strlen (ma0[1].a5_7[0]) < 5);
391 KEEP (strlen (ma0[9].a5_7[0]) < 5);
392 KEEP (strlen (ma0[9].a5_7[4]) < 5);
393 KEEP (strlen (ma0[i].a5_7[4]) < 5);
394 KEEP (strlen (ma0[i].a5_7[i]) < 5);
395
eef2da67
MS
396 /* Same as above. */
397 KEEP (strlen (ma0[i].a5_7[i]) > sizeof ma0[i].a5_7);
398
c42d0aa0
MS
399 KEEP (strlen (ma0->a0) < DIFF_MAX - 2);
400 KEEP (strlen (ma0->a0) < 999);
401 KEEP (strlen (ma0->a0) < 1);
402
403 KEEP (strlen (max->ax) < DIFF_MAX - 2);
404 KEEP (strlen (max->ax) < 999);
405 KEEP (strlen (max->ax) < 1);
406
407 KEEP (strlen (ma7->a7) < DIFF_MAX - 2);
408 KEEP (strlen (ma7->a7) < 999);
409 KEEP (strlen (ma7->a7) < 1);
410}
411
412void keep_pointers (const char *s)
413{
414 KEEP (strlen (ptr) < DIFF_MAX - 2);
415 KEEP (strlen (ptr) < 999);
416 KEEP (strlen (ptr) < 1);
417
418 KEEP (strlen (s) < DIFF_MAX - 2);
419 KEEP (strlen (s) < 999);
420 KEEP (strlen (s) < 1);
421}
422
423
424/* { dg-final { scan-tree-dump-times "call_in_true_branch_not_eliminated_" 0 "optimized" } }
425 { dg-final { scan-tree-dump-times "call_in_false_branch_not_eliminated_" 0 "optimized" } }
426
eef2da67
MS
427 { dg-final { scan-tree-dump-times "call_made_in_true_branch_on_line_1\[0-9\]\[0-9\]\[0-9\]" 119 "optimized" } }
428 { dg-final { scan-tree-dump-times "call_made_in_false_branch_on_line_1\[0-9\]\[0-9\]\[0-9\]" 119 "optimized" } } */