1 /* PR tree-optimization/83671 - fix for false positive reported by
2 -Wstringop-overflow does not work with inlining
4 { dg-options "-O1 -fdump-tree-optimized" } */
8 #define DIFF_MAX __PTRDIFF_MAX__
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__)
14 #define FAIL(name) do { \
15 extern void FAILNAME (name) (void); \
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
27 #define ELIM_FALSE(expr) \
28 if (!!(expr)) FAIL (in_false_branch_not_eliminated); else (void)0
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. */
38 FAIL (made_in_true_branch); \
40 FAIL (made_in_false_branch)
42 typedef char A3
[3], A5
[5], A7
[7], AX
[];
72 char a3
[3], a5
[5], a0
[0];
74 struct MemArraysX
{ char a3
[3], a5
[5], ax
[]; };
75 struct MemArrays7
{ char a3
[3], a5
[5], a7
[7]; };
77 struct MemArrays0 ma0_3_5_7
[3][5][7];
79 void elim_strings (int i
)
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);
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);
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);
93 ELIM_TRUE (strlen (i
< 0 ? "123" : "4321") <= 4);
94 ELIM_TRUE (strlen (i
< 0 ? "1234" : "321") <= 4);
96 ELIM_TRUE (strlen (i
< 0 ? "1" : "123456789") <= 9);
97 ELIM_TRUE (strlen (i
< 0 ? "1" : "123456789") >= 1);
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. */
103 void elim_global_arrays (int i
)
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. */
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
);
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
);
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
);
126 ELIM_TRUE (strlen (a3
) < sizeof a3
);
127 ELIM_TRUE (strlen (a7
) < sizeof a7
);
129 ELIM_TRUE (strlen (ax
) != DIFF_MAX
);
130 /* ELIM_TRUE (strlen (ax) != DIFF_MAX - 1); */
131 /* ELIM_TRUE (strlen (ax) < DIFF_MAX - 1); */
134 void elim_pointer_to_arrays (void)
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
);
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
);
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
);
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
);
157 void elim_global_arrays_and_strings (int i
)
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);
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);
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);
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);
184 void elim_member_arrays_obj (int i
)
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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. */
221 void keep_global_arrays (int i
)
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);
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);
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);
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);
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);
254 KEEP (strlen (a3
) < 2);
255 KEEP (strlen (a7
) < 6);
257 KEEP (strlen (a3
+ i
) < 2);
258 KEEP (strlen (a7
+ i
) < 2);
260 /* The length of an array of unknown size may be as large as
262 KEEP (strlen (ax
) != DIFF_MAX
- 2);
263 KEEP (strlen (ax
) < DIFF_MAX
- 2);
264 KEEP (strlen (ax
) < 999);
265 KEEP (strlen (ax
) < 1);
268 void keep_pointer_to_arrays (int i
)
270 KEEP (strlen (*pa7
) < 6);
271 KEEP (strlen (*pa5
) < 4);
272 KEEP (strlen (*pa3
) < 2);
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
);
283 KEEP (strlen ((*pa7_3
)[0]) < 2);
284 KEEP (strlen ((*pa7_3
)[1]) < 2);
285 KEEP (strlen ((*pa7_3
)[6]) < 2);
286 KEEP (strlen ((*pa7_3
)[i
]) < 2);
289 KEEP (strlen ((*pa7_3
)[0]) > sizeof *pa7_3
);
290 KEEP (strlen ((*pa7_3
)[i
]) > sizeof *pa7_3
);
292 KEEP (strlen ((*pax_3
)[0]) < 2);
293 KEEP (strlen ((*pax_3
)[1]) < 2);
294 KEEP (strlen ((*pax_3
)[9]) < 2);
295 KEEP (strlen ((*pax_3
)[i
]) < 2);
298 KEEP (strlen ((*pax_3
)[0]) > 3);
299 KEEP (strlen ((*pax_3
)[i
]) > 333);
301 KEEP (strlen ((*pa5_7
)[0]) < 6);
302 KEEP (strlen ((*pa5_7
)[1]) < 6);
303 KEEP (strlen ((*pa5_7
)[4]) < 6);
304 KEEP (strlen ((*pa5_7
)[i
]) < 6);
307 KEEP (strlen ((*pa5_7
)[0]) > sizeof *pa5_7
);
308 KEEP (strlen ((*pa5_7
)[i
]) > sizeof *pa5_7
);
311 void keep_global_arrays_and_strings (int i
)
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);
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);
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);
332 void keep_member_arrays_obj (int i
)
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);
339 KEEP (strlen (ma0_3_5_7
[1][0][0].a3
) < 2);
340 KEEP (strlen (ma0_3_5_7
[2][0][1].a3
) < 2);
342 KEEP (strlen (ma0_3_5_7
[1][1][0].a3
) < 2);
343 KEEP (strlen (ma0_3_5_7
[2][4][6].a3
) < 2);
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);
350 KEEP (strlen (ma0_3_5_7
[1][0][0].a5
) < 4);
351 KEEP (strlen (ma0_3_5_7
[2][0][1].a5
) < 4);
353 KEEP (strlen (ma0_3_5_7
[1][1][0].a5
) < 4);
354 KEEP (strlen (ma0_3_5_7
[2][4][6].a5
) < 4);
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);
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);
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);
369 void keep_member_arrays_ptr (struct MemArrays0
*ma0
,
370 struct MemArraysX
*max
,
371 struct MemArrays7
*ma7
,
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);
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
);
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);
397 KEEP (strlen (ma0
[i
].a5_7
[i
]) > sizeof ma0
[i
].a5_7
);
399 KEEP (strlen (ma0
->a0
) < DIFF_MAX
- 2);
400 KEEP (strlen (ma0
->a0
) < 999);
401 KEEP (strlen (ma0
->a0
) < 1);
403 KEEP (strlen (max
->ax
) < DIFF_MAX
- 2);
404 KEEP (strlen (max
->ax
) < 999);
405 KEEP (strlen (max
->ax
) < 1);
407 KEEP (strlen (ma7
->a7
) < DIFF_MAX
- 2);
408 KEEP (strlen (ma7
->a7
) < 999);
409 KEEP (strlen (ma7
->a7
) < 1);
412 void keep_pointers (const char *s
)
414 KEEP (strlen (ptr
) < DIFF_MAX
- 2);
415 KEEP (strlen (ptr
) < 999);
416 KEEP (strlen (ptr
) < 1);
418 KEEP (strlen (s
) < DIFF_MAX
- 2);
419 KEEP (strlen (s
) < 999);
420 KEEP (strlen (s
) < 1);
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" } }
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" } } */