1 /* PR tree-optimization/83671 - fix for false positive reported by
2    -Wstringop-overflow does not work with inlining
3    { dg-do compile }
4    { dg-options "-O1 -fdump-tree-optimized" } */
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 
42 typedef char A3[3], A5[5], A7[7], AX[];
43 
44 typedef A3 A7_3[7];
45 typedef A3 AX_3[];
46 typedef A5 A7_5[7];
47 typedef A7 A5_7[5];
48 
49 extern A7_3 a7_3;
50 extern A5_7 a5_7;
51 extern AX_3 ax_3;
52 
53 extern A3 a3;
54 extern A7 a5;
55 extern A7 a7;
56 extern AX ax;
57 
58 extern A3 *pa3;
59 extern A5 *pa5;
60 extern A7 *pa7;
61 
62 extern A7_3 *pa7_3;
63 extern AX_3 *pax_3;
64 extern A5_7 *pa5_7;
65 extern A7_5 *pa7_5;
66 
67 extern char *ptr;
68 
69 struct MemArrays0 {
70   A7_3 a7_3;
71   A5_7 a5_7;
72   char a3[3], a5[5], a0[0];
73 };
74 struct MemArraysX { char a3[3], a5[5], ax[]; };
75 struct MemArrays7 { char a3[3], a5[5], a7[7]; };
76 
77 struct MemArrays0 ma0_3_5_7[3][5][7];
78 
elim_strings(int i)79 void 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.  */
elim_global_arrays(int i)103 void 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.  */
108   ELIM_TRUE (strlen (a7_3[0]) < sizeof a7_3[0]);
109   ELIM_TRUE (strlen (a7_3[1]) < sizeof a7_3[1]);
110   ELIM_TRUE (strlen (a7_3[6]) < sizeof a7_3[6]);
111   ELIM_TRUE (strlen (a7_3[i]) < sizeof a7_3[i]);
112 
113   ELIM_TRUE (strlen (a5_7[0]) < sizeof a5_7[0]);
114   ELIM_TRUE (strlen (a5_7[1]) < sizeof a5_7[1]);
115   ELIM_TRUE (strlen (a5_7[4]) < sizeof a5_7[4]);
116   ELIM_TRUE (strlen (a5_7[i]) < sizeof a5_7[0]);
117 
118   ELIM_TRUE (strlen (ax_3[0]) < sizeof ax_3[0]);
119   ELIM_TRUE (strlen (ax_3[1]) < sizeof ax_3[1]);
120   ELIM_TRUE (strlen (ax_3[9]) < sizeof ax_3[9]);
121   ELIM_TRUE (strlen (ax_3[i]) < sizeof ax_3[i]);
122 
123   ELIM_TRUE (strlen (a3) < sizeof a3);
124   ELIM_TRUE (strlen (a7) < sizeof a7);
125 
126   ELIM_TRUE (strlen (ax) != DIFF_MAX);
127   ELIM_TRUE (strlen (ax) != DIFF_MAX - 1);
128   ELIM_TRUE (strlen (ax) < DIFF_MAX - 1);
129 }
130 
elim_pointer_to_arrays(void)131 void elim_pointer_to_arrays (void)
132 {
133   ELIM_TRUE (strlen (*pa7) < 7);
134   ELIM_TRUE (strlen (*pa5) < 5);
135   ELIM_TRUE (strlen (*pa3) < 3);
136 
137   ELIM_TRUE (strlen ((*pa7_3)[0]) < 3);
138   ELIM_TRUE (strlen ((*pa7_3)[1]) < 3);
139   ELIM_TRUE (strlen ((*pa7_3)[6]) < 3);
140 
141   ELIM_TRUE (strlen ((*pax_3)[0]) < 3);
142   ELIM_TRUE (strlen ((*pax_3)[1]) < 3);
143   ELIM_TRUE (strlen ((*pax_3)[9]) < 3);
144 
145   ELIM_TRUE (strlen ((*pa5_7)[0]) < 7);
146   ELIM_TRUE (strlen ((*pa5_7)[1]) < 7);
147   ELIM_TRUE (strlen ((*pa5_7)[4]) < 7);
148 }
149 
elim_global_arrays_and_strings(int i)150 void elim_global_arrays_and_strings (int i)
151 {
152   ELIM_TRUE (strlen (i < 0 ? a3 : "") < 3);
153   ELIM_TRUE (strlen (i < 0 ? a3 : "1") < 3);
154   ELIM_TRUE (strlen (i < 0 ? a3 : "12") < 3);
155   ELIM_TRUE (strlen (i < 0 ? a3 : "123") < 4);
156 
157   ELIM_FALSE (strlen (i < 0 ? a3 : "") > 3);
158   ELIM_FALSE (strlen (i < 0 ? a3 : "1") > 3);
159   ELIM_FALSE (strlen (i < 0 ? a3 : "12") > 3);
160   ELIM_FALSE (strlen (i < 0 ? a3 : "123") > 4);
161 
162   ELIM_TRUE (strlen (i < 0 ? a7 : "") < 7);
163   ELIM_TRUE (strlen (i < 0 ? a7 : "1") < 7);
164   ELIM_TRUE (strlen (i < 0 ? a7 : "12") < 7);
165   ELIM_TRUE (strlen (i < 0 ? a7 : "123") < 7);
166   ELIM_TRUE (strlen (i < 0 ? a7 : "123456") < 7);
167   ELIM_TRUE (strlen (i < 0 ? a7 : "1234567") < 8);
168 
169   ELIM_FALSE (strlen (i < 0 ? a7 : "") > 6);
170   ELIM_FALSE (strlen (i < 0 ? a7 : "1") > 6);
171   ELIM_FALSE (strlen (i < 0 ? a7 : "12") > 6);
172   ELIM_FALSE (strlen (i < 0 ? a7 : "123") > 6);
173   ELIM_FALSE (strlen (i < 0 ? a7 : "123456") > 7);
174   ELIM_FALSE (strlen (i < 0 ? a7 : "1234567") > 8);
175 }
176 
elim_member_arrays_obj(int i)177 void elim_member_arrays_obj (int i)
178 {
179   ELIM_TRUE (strlen (ma0_3_5_7[0][0][0].a3) < 3);
180   ELIM_TRUE (strlen (ma0_3_5_7[0][0][1].a3) < 3);
181   ELIM_TRUE (strlen (ma0_3_5_7[0][0][2].a3) < 3);
182   ELIM_TRUE (strlen (ma0_3_5_7[0][0][6].a3) < 3);
183 
184   ELIM_TRUE (strlen (ma0_3_5_7[1][0][0].a3) < 3);
185   ELIM_TRUE (strlen (ma0_3_5_7[2][0][1].a3) < 3);
186 
187   ELIM_TRUE (strlen (ma0_3_5_7[1][1][0].a3) < 3);
188   ELIM_TRUE (strlen (ma0_3_5_7[2][4][6].a3) < 3);
189 
190   ELIM_TRUE (strlen (ma0_3_5_7[0][0][0].a5) < 5);
191   ELIM_TRUE (strlen (ma0_3_5_7[0][0][1].a5) < 5);
192   ELIM_TRUE (strlen (ma0_3_5_7[0][0][2].a5) < 5);
193   ELIM_TRUE (strlen (ma0_3_5_7[0][0][6].a5) < 5);
194 
195   ELIM_TRUE (strlen (ma0_3_5_7[1][0][0].a5) < 5);
196   ELIM_TRUE (strlen (ma0_3_5_7[2][0][1].a5) < 5);
197 
198   ELIM_TRUE (strlen (ma0_3_5_7[1][1][0].a5) < 5);
199   ELIM_TRUE (strlen (ma0_3_5_7[2][4][6].a5) < 5);
200 
201   ELIM_TRUE (strlen (ma0_3_5_7[0][0][0].a7_3[0]) < 3);
202   ELIM_TRUE (strlen (ma0_3_5_7[2][4][6].a7_3[2]) < 3);
203 
204   ELIM_TRUE (strlen (ma0_3_5_7[0][0][0].a5_7[0]) < 7);
205   ELIM_TRUE (strlen (ma0_3_5_7[2][4][6].a5_7[4]) < 7);
206 }
207 
elim_member_arrays_ptr(struct MemArrays0 * ma0,struct MemArraysX * max,struct MemArrays7 * ma7,int i)208 void elim_member_arrays_ptr (struct MemArrays0 *ma0,
209 			     struct MemArraysX *max,
210 			     struct MemArrays7 *ma7,
211 			     int i)
212 {
213   ELIM_TRUE (strlen (ma0->a7_3[0]) < 3);
214   ELIM_TRUE (strlen (ma0->a7_3[1]) < 3);
215   ELIM_TRUE (strlen (ma0->a7_3[6]) < 3);
216   ELIM_TRUE (strlen (ma0->a7_3[6]) < 3);
217   ELIM_TRUE (strlen (ma0->a7_3[i]) < 3);
218   ELIM_TRUE (strlen (ma0->a7_3[i]) < 3);
219 
220   ELIM_TRUE (strlen (ma0->a5_7[0]) < 7);
221   ELIM_TRUE (strlen (ma0[0].a5_7[0]) < 7);
222   ELIM_TRUE (strlen (ma0[1].a5_7[0]) < 7);
223   ELIM_TRUE (strlen (ma0[1].a5_7[4]) < 7);
224   ELIM_TRUE (strlen (ma0[9].a5_7[0]) < 7);
225   ELIM_TRUE (strlen (ma0[9].a5_7[4]) < 7);
226 
227   ELIM_TRUE (strlen (ma0->a3) < sizeof ma0->a3);
228   ELIM_TRUE (strlen (ma0->a5) < sizeof ma0->a5);
229   ELIM_TRUE (strlen (ma0->a0) < DIFF_MAX - 1);
230 
231   ELIM_TRUE (strlen (max->a3) < sizeof max->a3);
232   ELIM_TRUE (strlen (max->a5) < sizeof max->a5);
233   ELIM_TRUE (strlen (max->ax) < DIFF_MAX - 1);
234 
235   ELIM_TRUE (strlen (ma7->a3) < sizeof max->a3);
236   ELIM_TRUE (strlen (ma7->a5) < sizeof max->a5);
237   ELIM_TRUE (strlen (ma7->a7) < DIFF_MAX - 1);
238 }
239 
240 
241 #line 1000
242 
243 /* Verify that strlen calls involving uninitialized global arrays
244    of unknown size are not eliminated when they appear in expressions
245    that test for results that need not be true.  */
keep_global_arrays(int i)246 void keep_global_arrays (int i)
247 {
248   KEEP (strlen (a7_3[0]) < 2);
249   KEEP (strlen (a7_3[1]) < 2);
250   KEEP (strlen (a7_3[6]) < 2);
251   KEEP (strlen (a7_3[i]) < 2);
252 
253   KEEP (strlen (a5_7[0]) < 6);
254   KEEP (strlen (a5_7[1]) < 6);
255   KEEP (strlen (a5_7[4]) < 6);
256   KEEP (strlen (a5_7[i]) < 6);
257 
258   KEEP (strlen (ax_3[0]) < 2);
259   KEEP (strlen (ax_3[1]) < 2);
260   KEEP (strlen (ax_3[2]) < 2);
261   KEEP (strlen (ax_3[i]) < 2);
262 
263   KEEP (strlen (a3) < 2);
264   KEEP (strlen (a7) < 6);
265 
266   KEEP (strlen (a3 + i) < 2);
267   KEEP (strlen (a7 + i) < 2);
268 
269   /* The length of an array of unknown size may be as large as
270      DIFF_MAX - 2.  */
271   KEEP (strlen (ax) != DIFF_MAX - 2);
272   KEEP (strlen (ax) < DIFF_MAX - 2);
273   KEEP (strlen (ax) < 999);
274   KEEP (strlen (ax) < 1);
275 }
276 
keep_pointer_to_arrays(void)277 void keep_pointer_to_arrays (void)
278 {
279   KEEP (strlen (*pa7) < 6);
280   KEEP (strlen (*pa5) < 4);
281   KEEP (strlen (*pa3) < 2);
282 
283   KEEP (strlen ((*pa7_3)[0]) < 2);
284   KEEP (strlen ((*pa7_3)[1]) < 2);
285   KEEP (strlen ((*pa7_3)[6]) < 2);
286 
287   KEEP (strlen ((*pax_3)[0]) < 2);
288   KEEP (strlen ((*pax_3)[1]) < 2);
289   KEEP (strlen ((*pax_3)[9]) < 2);
290 
291   KEEP (strlen ((*pa5_7)[0]) < 6);
292   KEEP (strlen ((*pa5_7)[1]) < 6);
293   KEEP (strlen ((*pa5_7)[4]) < 6);
294 }
295 
keep_global_arrays_and_strings(int i)296 void keep_global_arrays_and_strings (int i)
297 {
298   KEEP (strlen (i < 0 ? a3 : "") < 2);
299   KEEP (strlen (i < 0 ? a3 : "1") < 2);
300   KEEP (strlen (i < 0 ? a3 : "12") < 2);
301   KEEP (strlen (i < 0 ? a3 : "123") < 3);
302 
303   KEEP (strlen (i < 0 ? a7 : "") < 5);
304   KEEP (strlen (i < 0 ? a7 : "1") < 5);
305   KEEP (strlen (i < 0 ? a7 : "12") < 5);
306   KEEP (strlen (i < 0 ? a7 : "123") < 5);
307   KEEP (strlen (i < 0 ? a7 : "123456") < 6);
308   KEEP (strlen (i < 0 ? a7 : "1234567") < 6);
309 }
310 
keep_member_arrays_obj(int i)311 void keep_member_arrays_obj (int i)
312 {
313   KEEP (strlen (ma0_3_5_7[0][0][0].a3) < 2);
314   KEEP (strlen (ma0_3_5_7[0][0][1].a3) < 2);
315   KEEP (strlen (ma0_3_5_7[0][0][2].a3) < 2);
316   KEEP (strlen (ma0_3_5_7[0][0][6].a3) < 2);
317 
318   KEEP (strlen (ma0_3_5_7[1][0][0].a3) < 2);
319   KEEP (strlen (ma0_3_5_7[2][0][1].a3) < 2);
320 
321   KEEP (strlen (ma0_3_5_7[1][1][0].a3) < 2);
322   KEEP (strlen (ma0_3_5_7[2][4][6].a3) < 2);
323 
324   KEEP (strlen (ma0_3_5_7[0][0][0].a5) < 4);
325   KEEP (strlen (ma0_3_5_7[0][0][1].a5) < 4);
326   KEEP (strlen (ma0_3_5_7[0][0][2].a5) < 4);
327   KEEP (strlen (ma0_3_5_7[0][0][6].a5) < 4);
328 
329   KEEP (strlen (ma0_3_5_7[1][0][0].a5) < 4);
330   KEEP (strlen (ma0_3_5_7[2][0][1].a5) < 4);
331 
332   KEEP (strlen (ma0_3_5_7[1][1][0].a5) < 4);
333   KEEP (strlen (ma0_3_5_7[2][4][6].a5) < 4);
334 
335   KEEP (strlen (ma0_3_5_7[0][0][0].a7_3[0]) < 2);
336   KEEP (strlen (ma0_3_5_7[2][4][6].a7_3[2]) < 2);
337 
338   KEEP (strlen (ma0_3_5_7[0][0][0].a5_7[0]) < 6);
339   KEEP (strlen (ma0_3_5_7[2][4][6].a5_7[4]) < 6);
340 }
341 
keep_member_arrays_ptr(struct MemArrays0 * ma0,struct MemArraysX * max,struct MemArrays7 * ma7,int i)342 void keep_member_arrays_ptr (struct MemArrays0 *ma0,
343 			     struct MemArraysX *max,
344 			     struct MemArrays7 *ma7,
345 			     int i)
346 {
347   KEEP (strlen (ma0->a7_3[0]) > 0);
348   KEEP (strlen (ma0->a7_3[0]) < 2);
349   KEEP (strlen (ma0->a7_3[1]) < 2);
350   KEEP (strlen (ma0->a7_3[6]) < 2);
351   KEEP (strlen (ma0->a7_3[6]) < 2);
352   KEEP (strlen (ma0->a7_3[i]) > 0);
353   KEEP (strlen (ma0->a7_3[i]) < 2);
354   KEEP (strlen (ma0->a7_3[i]) < 2);
355 
356   KEEP (strlen (ma0->a5_7[0]) < 5);
357   KEEP (strlen (ma0[0].a5_7[0]) < 5);
358   KEEP (strlen (ma0[1].a5_7[0]) < 5);
359   KEEP (strlen (ma0[9].a5_7[0]) < 5);
360   KEEP (strlen (ma0[9].a5_7[4]) < 5);
361   KEEP (strlen (ma0[i].a5_7[4]) < 5);
362   KEEP (strlen (ma0[i].a5_7[i]) < 5);
363 
364   KEEP (strlen (ma0->a0) < DIFF_MAX - 2);
365   KEEP (strlen (ma0->a0) < 999);
366   KEEP (strlen (ma0->a0) < 1);
367 
368   KEEP (strlen (max->ax) < DIFF_MAX - 2);
369   KEEP (strlen (max->ax) < 999);
370   KEEP (strlen (max->ax) < 1);
371 
372   KEEP (strlen (ma7->a7) < DIFF_MAX - 2);
373   KEEP (strlen (ma7->a7) < 999);
374   KEEP (strlen (ma7->a7) < 1);
375 }
376 
keep_pointers(const char * s)377 void keep_pointers (const char *s)
378 {
379   KEEP (strlen (ptr) < DIFF_MAX - 2);
380   KEEP (strlen (ptr) < 999);
381   KEEP (strlen (ptr) < 1);
382 
383   KEEP (strlen (s) < DIFF_MAX - 2);
384   KEEP (strlen (s) < 999);
385   KEEP (strlen (s) < 1);
386 }
387 
388 
389 /* { dg-final { scan-tree-dump-times "call_in_true_branch_not_eliminated_" 0 "optimized" } }
390    { dg-final { scan-tree-dump-times "call_in_false_branch_not_eliminated_" 0 "optimized" } }
391 
392    { dg-final { scan-tree-dump-times "call_made_in_true_branch_on_line_1\[0-9\]\[0-9\]\[0-9\]" 92 "optimized" } }
393    { dg-final { scan-tree-dump-times "call_made_in_false_branch_on_line_1\[0-9\]\[0-9\]\[0-9\]" 92 "optimized" } } */
394