Attachment 'sprintf.patch'
Download 1 commit 2e89a51dae7d72eba3d872c9f813056ab4a5086e
2 Author: aldyh <aldyh@138bc75d-0d04-0410-961f-82ee72b054a4>
3 Date: Fri May 25 11:08:18 2018 +0000
4
5 Rangerize sprintf warning pass.
6
7 git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/ssa-range@260751 138bc75d-0d04-0410-961f-82ee72b054a4
8
9 diff --git a/gcc/gimple-ssa-sprintf.c b/gcc/gimple-ssa-sprintf.c
10 index 4ec58605ce8..4a2a195f8a1 100644
11 --- a/gcc/gimple-ssa-sprintf.c
12 +++ b/gcc/gimple-ssa-sprintf.c
13 @@ -83,6 +83,7 @@ along with GCC; see the file COPYING3. If not see
14 #include "alloc-pool.h"
15 #include "vr-values.h"
16 #include "gimple-ssa-evrp-analyze.h"
17 +#include "ssa-range.h"
18
19 /* The likely worst case value of MB_LEN_MAX for the target, large enough
20 for UTF-8. Ideally, this would be obtained by a target hook if it were
21 @@ -117,21 +118,6 @@ static int warn_level;
22
23 struct format_result;
24
25 -class sprintf_dom_walker : public dom_walker
26 -{
27 - public:
28 - sprintf_dom_walker () : dom_walker (CDI_DOMINATORS) {}
29 - ~sprintf_dom_walker () {}
30 -
31 - edge before_dom_children (basic_block) FINAL OVERRIDE;
32 - void after_dom_children (basic_block) FINAL OVERRIDE;
33 - bool handle_gimple_call (gimple_stmt_iterator *);
34 -
35 - struct call_info;
36 - bool compute_format_length (call_info &, format_result *);
37 - class evrp_range_analyzer evrp_range_analyzer;
38 -};
39 -
40 class pass_sprintf_length : public gimple_opt_pass
41 {
42 bool fold_return_value;
43 @@ -794,7 +780,7 @@ fmtresult::type_max_digits (tree type, int base)
44
45 static bool
46 get_int_range (tree, HOST_WIDE_INT *, HOST_WIDE_INT *, bool, HOST_WIDE_INT,
47 - class vr_values *vr_values);
48 + gimple *);
49
50 /* Description of a format directive. A directive is either a plain
51 string or a conversion specification that starts with '%'. */
52 @@ -823,13 +809,15 @@ struct directive
53 /* Format specifier character. */
54 char specifier;
55
56 + gimple *callstmt;
57 +
58 /* The argument of the directive or null when the directive doesn't
59 take one or when none is available (such as for vararg functions). */
60 tree arg;
61
62 /* Format conversion function that given a directive and an argument
63 returns the formatting result. */
64 - fmtresult (*fmtfunc) (const directive &, tree, vr_values *);
65 + fmtresult (*fmtfunc) (const directive &, tree);
66
67 /* Return True when a the format flag CHR has been used. */
68 bool get_flag (char chr) const
69 @@ -866,9 +854,9 @@ struct directive
70 or 0, whichever is greater. For a non-constant ARG in some range
71 set width to its range adjusting each bound to -1 if it's less.
72 For an indeterminate ARG set width to [0, INT_MAX]. */
73 - void set_width (tree arg, vr_values *vr_values)
74 + void set_width (tree arg)
75 {
76 - get_int_range (arg, width, width + 1, true, 0, vr_values);
77 + get_int_range (arg, width, width + 1, true, 0, callstmt);
78 }
79
80 /* Set both bounds of the precision range to VAL. */
81 @@ -882,9 +870,9 @@ struct directive
82 or -1 whichever is greater. For a non-constant ARG in some range
83 set precision to its range adjusting each bound to -1 if it's less.
84 For an indeterminate ARG set precision to [-1, INT_MAX]. */
85 - void set_precision (tree arg, vr_values *vr_values)
86 + void set_precision (tree arg)
87 {
88 - get_int_range (arg, prec, prec + 1, false, -1, vr_values);
89 + get_int_range (arg, prec, prec + 1, false, -1, callstmt);
90 }
91
92 /* Return true if both width and precision are known to be
93 @@ -1014,7 +1002,7 @@ bytes_remaining (unsigned HOST_WIDE_INT navail, const format_result &res)
94
95 /* Description of a call to a formatted function. */
96
97 -struct sprintf_dom_walker::call_info
98 +struct call_info
99 {
100 /* Function call statement. */
101 gimple *callstmt;
102 @@ -1065,7 +1053,7 @@ struct sprintf_dom_walker::call_info
103 /* Return the result of formatting a no-op directive (such as '%n'). */
104
105 static fmtresult
106 -format_none (const directive &, tree, vr_values *)
107 +format_none (const directive &, tree)
108 {
109 fmtresult res (0);
110 return res;
111 @@ -1074,7 +1062,7 @@ format_none (const directive &, tree, vr_values *)
112 /* Return the result of formatting the '%%' directive. */
113
114 static fmtresult
115 -format_percent (const directive &, tree, vr_values *)
116 +format_percent (const directive &, tree)
117 {
118 fmtresult res (1);
119 return res;
120 @@ -1132,7 +1120,7 @@ build_intmax_type_nodes (tree *pintmax, tree *puintmax)
121 static bool
122 get_int_range (tree arg, HOST_WIDE_INT *pmin, HOST_WIDE_INT *pmax,
123 bool absolute, HOST_WIDE_INT negbound,
124 - class vr_values *vr_values)
125 + gimple *call)
126 {
127 /* The type of the result. */
128 const_tree type = integer_type_node;
129 @@ -1171,10 +1159,8 @@ get_int_range (tree arg, HOST_WIDE_INT *pmin, HOST_WIDE_INT *pmax,
130 && TYPE_PRECISION (argtype) <= TYPE_PRECISION (type))
131 {
132 /* Try to determine the range of values of the integer argument. */
133 - value_range *vr = vr_values->get_value_range (arg);
134 - if (vr->type == VR_RANGE
135 - && TREE_CODE (vr->min) == INTEGER_CST
136 - && TREE_CODE (vr->max) == INTEGER_CST)
137 + irange r;
138 + if (on_demand_get_range_on_stmt (r, arg, call))
139 {
140 HOST_WIDE_INT type_min
141 = (TYPE_UNSIGNED (argtype)
142 @@ -1183,8 +1169,10 @@ get_int_range (tree arg, HOST_WIDE_INT *pmin, HOST_WIDE_INT *pmax,
143
144 HOST_WIDE_INT type_max = tree_to_uhwi (TYPE_MAX_VALUE (argtype));
145
146 - *pmin = TREE_INT_CST_LOW (vr->min);
147 - *pmax = TREE_INT_CST_LOW (vr->max);
148 + tree max = wide_int_to_tree (TREE_TYPE (arg), r.upper_bound ());
149 + tree min = wide_int_to_tree (TREE_TYPE (arg), r.lower_bound ());
150 + *pmin = TREE_INT_CST_LOW (min);
151 + *pmax = TREE_INT_CST_LOW (max);
152
153 if (*pmin < *pmax)
154 {
155 @@ -1205,7 +1193,7 @@ get_int_range (tree arg, HOST_WIDE_INT *pmin, HOST_WIDE_INT *pmax,
156 provided. */
157 if (unknown)
158 return get_int_range (NULL_TREE, pmin, pmax, absolute,
159 - negbound, vr_values);
160 + negbound, call);
161 }
162
163 /* Adjust each bound as specified by ABSOLUTE and NEGBOUND. */
164 @@ -1290,7 +1278,7 @@ adjust_range_for_overflow (tree dirtype, tree *argmin, tree *argmax)
165 used when the directive argument or its value isn't known. */
166
167 static fmtresult
168 -format_integer (const directive &dir, tree arg, vr_values *vr_values)
169 +format_integer (const directive &dir, tree arg)
170 {
171 tree intmax_type_node;
172 tree uintmax_type_node;
173 @@ -1473,13 +1461,11 @@ format_integer (const directive &dir, tree arg, vr_values *vr_values)
174 {
175 /* Try to determine the range of values of the integer argument
176 (range information is not available for pointers). */
177 - value_range *vr = vr_values->get_value_range (arg);
178 - if (vr->type == VR_RANGE
179 - && TREE_CODE (vr->min) == INTEGER_CST
180 - && TREE_CODE (vr->max) == INTEGER_CST)
181 + irange r;
182 + if (on_demand_get_range_on_stmt (r, arg, dir.callstmt))
183 {
184 - argmin = vr->min;
185 - argmax = vr->max;
186 + argmin = wide_int_to_tree (TREE_TYPE (arg), r.lower_bound ());
187 + argmax = wide_int_to_tree (TREE_TYPE (arg), r.upper_bound ());
188
189 /* Set KNOWNRANGE if the argument is in a known subrange
190 of the directive's type and neither width nor precision
191 @@ -1492,12 +1478,7 @@ format_integer (const directive &dir, tree arg, vr_values *vr_values)
192 res.argmin = argmin;
193 res.argmax = argmax;
194 }
195 - else if (vr->type == VR_ANTI_RANGE)
196 - {
197 - /* Handle anti-ranges if/when bug 71690 is resolved. */
198 - }
199 - else if (vr->type == VR_VARYING
200 - || vr->type == VR_UNDEFINED)
201 + else
202 {
203 /* The argument here may be the result of promoting the actual
204 argument to int. Try to determine the type of the actual
205 @@ -1510,7 +1491,7 @@ format_integer (const directive &dir, tree arg, vr_values *vr_values)
206 if (code == INTEGER_CST)
207 {
208 arg = gimple_assign_rhs1 (def);
209 - return format_integer (dir, arg, vr_values);
210 + return format_integer (dir, arg);
211 }
212
213 if (code == NOP_EXPR)
214 @@ -1555,16 +1536,16 @@ format_integer (const directive &dir, tree arg, vr_values *vr_values)
215 /* For unsigned conversions/directives or signed when
216 the minimum is positive, use the minimum and maximum to compute
217 the shortest and longest output, respectively. */
218 - res.range.min = format_integer (dir, argmin, vr_values).range.min;
219 - res.range.max = format_integer (dir, argmax, vr_values).range.max;
220 + res.range.min = format_integer (dir, argmin).range.min;
221 + res.range.max = format_integer (dir, argmax).range.max;
222 }
223 else if (tree_int_cst_sgn (argmax) < 0)
224 {
225 /* For signed conversions/directives if maximum is negative,
226 use the minimum as the longest output and maximum as the
227 shortest output. */
228 - res.range.min = format_integer (dir, argmax, vr_values).range.min;
229 - res.range.max = format_integer (dir, argmin, vr_values).range.max;
230 + res.range.min = format_integer (dir, argmax).range.min;
231 + res.range.max = format_integer (dir, argmin).range.max;
232 }
233 else
234 {
235 @@ -1573,11 +1554,11 @@ format_integer (const directive &dir, tree arg, vr_values *vr_values)
236 length of the output of both minimum and maximum and pick the
237 longer. */
238 unsigned HOST_WIDE_INT max1
239 - = format_integer (dir, argmin, vr_values).range.max;
240 + = format_integer (dir, argmin).range.max;
241 unsigned HOST_WIDE_INT max2
242 - = format_integer (dir, argmax, vr_values).range.max;
243 + = format_integer (dir, argmax).range.max;
244 res.range.min
245 - = format_integer (dir, integer_zero_node, vr_values).range.min;
246 + = format_integer (dir, integer_zero_node).range.min;
247 res.range.max = MAX (max1, max2);
248 }
249
250 @@ -1918,7 +1899,7 @@ format_floating (const directive &dir, const HOST_WIDE_INT prec[2])
251 ARG. */
252
253 static fmtresult
254 -format_floating (const directive &dir, tree arg, vr_values *)
255 +format_floating (const directive &dir, tree arg)
256 {
257 HOST_WIDE_INT prec[] = { dir.prec[0], dir.prec[1] };
258 tree type = (dir.modifier == FMT_LEN_L || dir.modifier == FMT_LEN_ll
259 @@ -2158,7 +2139,7 @@ get_string_length (tree str)
260 vsprinf). */
261
262 static fmtresult
263 -format_character (const directive &dir, tree arg, vr_values *vr_values)
264 +format_character (const directive &dir, tree arg)
265 {
266 fmtresult res;
267
268 @@ -2170,7 +2151,7 @@ format_character (const directive &dir, tree arg, vr_values *vr_values)
269 res.range.min = 0;
270
271 HOST_WIDE_INT min, max;
272 - if (get_int_range (arg, &min, &max, false, 0, vr_values))
273 + if (get_int_range (arg, &min, &max, false, 0, dir.callstmt))
274 {
275 if (min == 0 && max == 0)
276 {
277 @@ -2223,7 +2204,7 @@ format_character (const directive &dir, tree arg, vr_values *vr_values)
278 vsprinf). */
279
280 static fmtresult
281 -format_string (const directive &dir, tree arg, vr_values *)
282 +format_string (const directive &dir, tree arg)
283 {
284 fmtresult res;
285
286 @@ -2384,7 +2365,7 @@ format_string (const directive &dir, tree arg, vr_values *)
287 /* Format plain string (part of the format string itself). */
288
289 static fmtresult
290 -format_plain (const directive &dir, tree, vr_values *)
291 +format_plain (const directive &dir, tree)
292 {
293 fmtresult res (dir.len);
294 return res;
295 @@ -2394,7 +2375,7 @@ format_plain (const directive &dir, tree, vr_values *)
296 should be diagnosed given the AVAILable space in the destination. */
297
298 static bool
299 -should_warn_p (const sprintf_dom_walker::call_info &info,
300 +should_warn_p (const call_info &info,
301 const result_range &avail, const result_range &result)
302 {
303 if (result.max <= avail.min)
304 @@ -2465,7 +2446,7 @@ should_warn_p (const sprintf_dom_walker::call_info &info,
305
306 static bool
307 maybe_warn (substring_loc &dirloc, location_t argloc,
308 - const sprintf_dom_walker::call_info &info,
309 + const call_info &info,
310 const result_range &avail_range, const result_range &res,
311 const directive &dir)
312 {
313 @@ -2745,9 +2726,8 @@ maybe_warn (substring_loc &dirloc, location_t argloc,
314 in *RES. Return true if the directive has been handled. */
315
316 static bool
317 -format_directive (const sprintf_dom_walker::call_info &info,
318 - format_result *res, const directive &dir,
319 - class vr_values *vr_values)
320 +format_directive (const call_info &info,
321 + format_result *res, const directive &dir)
322 {
323 /* Offset of the beginning of the directive from the beginning
324 of the format string. */
325 @@ -2772,7 +2752,7 @@ format_directive (const sprintf_dom_walker::call_info &info,
326 return false;
327
328 /* Compute the range of lengths of the formatted output. */
329 - fmtresult fmtres = dir.fmtfunc (dir, dir.arg, vr_values);
330 + fmtresult fmtres = dir.fmtfunc (dir, dir.arg);
331
332 /* Record whether the output of all directives is known to be
333 bounded by some maximum, implying that their arguments are
334 @@ -3021,13 +3001,13 @@ format_directive (const sprintf_dom_walker::call_info &info,
335 the directive. */
336
337 static size_t
338 -parse_directive (sprintf_dom_walker::call_info &info,
339 +parse_directive (call_info &info,
340 directive &dir, format_result *res,
341 - const char *str, unsigned *argno,
342 - vr_values *vr_values)
343 + const char *str, unsigned *argno)
344 {
345 const char *pcnt = strchr (str, target_percent);
346 dir.beg = str;
347 + dir.callstmt = info.callstmt;
348
349 if (size_t len = pcnt ? pcnt - str : *str ? strlen (str) : 1)
350 {
351 @@ -3342,7 +3322,7 @@ parse_directive (sprintf_dom_walker::call_info &info,
352 if (star_width)
353 {
354 if (INTEGRAL_TYPE_P (TREE_TYPE (star_width)))
355 - dir.set_width (star_width, vr_values);
356 + dir.set_width (star_width);
357 else
358 {
359 /* Width specified by a va_list takes on the range [0, -INT_MIN]
360 @@ -3375,7 +3355,7 @@ parse_directive (sprintf_dom_walker::call_info &info,
361 if (star_precision)
362 {
363 if (INTEGRAL_TYPE_P (TREE_TYPE (star_precision)))
364 - dir.set_precision (star_precision, vr_values);
365 + dir.set_precision (star_precision);
366 else
367 {
368 /* Precision specified by a va_list takes on the range [-1, INT_MAX]
369 @@ -3458,9 +3438,8 @@ parse_directive (sprintf_dom_walker::call_info &info,
370 on, false otherwise (e.g., when a unknown or unhandled directive was seen
371 that caused the processing to be terminated early). */
372
373 -bool
374 -sprintf_dom_walker::compute_format_length (call_info &info,
375 - format_result *res)
376 +static bool
377 +compute_format_length (call_info &info, format_result *res)
378 {
379 if (dump_file)
380 {
381 @@ -3497,12 +3476,10 @@ sprintf_dom_walker::compute_format_length (call_info &info,
382 directive dir = directive ();
383 dir.dirno = dirno;
384
385 - size_t n = parse_directive (info, dir, res, pf, &argno,
386 - evrp_range_analyzer.get_vr_values ());
387 + size_t n = parse_directive (info, dir, res, pf, &argno);
388
389 /* Return failure if the format function fails. */
390 - if (!format_directive (info, res, dir,
391 - evrp_range_analyzer.get_vr_values ()))
392 + if (!format_directive (info, res, dir))
393 return false;
394
395 /* Return success the directive is zero bytes long and it's
396 @@ -3546,7 +3523,7 @@ get_destination_size (tree dest)
397 of its return values. */
398
399 static bool
400 -is_call_safe (const sprintf_dom_walker::call_info &info,
401 +is_call_safe (const call_info &info,
402 const format_result &res, bool under4k,
403 unsigned HOST_WIDE_INT retval[2])
404 {
405 @@ -3605,7 +3582,7 @@ is_call_safe (const sprintf_dom_walker::call_info &info,
406
407 static bool
408 try_substitute_return_value (gimple_stmt_iterator *gsi,
409 - const sprintf_dom_walker::call_info &info,
410 + const call_info &info,
411 const format_result &res)
412 {
413 tree lhs = gimple_get_lhs (info.callstmt);
414 @@ -3723,7 +3700,7 @@ try_substitute_return_value (gimple_stmt_iterator *gsi,
415
416 static bool
417 try_simplify_call (gimple_stmt_iterator *gsi,
418 - const sprintf_dom_walker::call_info &info,
419 + const call_info &info,
420 const format_result &res)
421 {
422 unsigned HOST_WIDE_INT dummy[2];
423 @@ -3749,8 +3726,8 @@ try_simplify_call (gimple_stmt_iterator *gsi,
424 functions and if so, handle it. Return true if the call is removed
425 and gsi_next should not be performed in the caller. */
426
427 -bool
428 -sprintf_dom_walker::handle_gimple_call (gimple_stmt_iterator *gsi)
429 +static bool
430 +handle_gimple_call (gimple_stmt_iterator *gsi)
431 {
432 call_info info = call_info ();
433
434 @@ -3904,13 +3881,15 @@ sprintf_dom_walker::handle_gimple_call (gimple_stmt_iterator *gsi)
435 /* Try to determine the range of values of the argument
436 and use the greater of the two at level 1 and the smaller
437 of them at level 2. */
438 - value_range *vr = evrp_range_analyzer.get_value_range (size);
439 - if (vr->type == VR_RANGE
440 - && TREE_CODE (vr->min) == INTEGER_CST
441 - && TREE_CODE (vr->max) == INTEGER_CST)
442 - dstsize = (warn_level < 2
443 - ? TREE_INT_CST_LOW (vr->max)
444 - : TREE_INT_CST_LOW (vr->min));
445 + irange r;
446 + if (on_demand_get_range_on_stmt (r, size, info.callstmt))
447 + {
448 + tree max = wide_int_to_tree (TREE_TYPE (size), r.upper_bound ());
449 + tree min = wide_int_to_tree (TREE_TYPE (size), r.lower_bound ());
450 + dstsize = (warn_level < 2
451 + ? TREE_INT_CST_LOW (max)
452 + : TREE_INT_CST_LOW (min));
453 + }
454
455 /* The destination size is not constant. If the function is
456 bounded (e.g., snprintf) a lower bound of zero doesn't
457 @@ -4012,18 +3991,14 @@ sprintf_dom_walker::handle_gimple_call (gimple_stmt_iterator *gsi)
458 return call_removed;
459 }
460
461 -edge
462 -sprintf_dom_walker::before_dom_children (basic_block bb)
463 +static void
464 +sprintf_walk (basic_block bb)
465 {
466 - evrp_range_analyzer.enter (bb);
467 for (gimple_stmt_iterator si = gsi_start_bb (bb); !gsi_end_p (si); )
468 {
469 /* Iterate over statements, looking for function calls. */
470 gimple *stmt = gsi_stmt (si);
471
472 - /* First record ranges generated by this statement. */
473 - evrp_range_analyzer.record_ranges_from_stmt (stmt, false);
474 -
475 if (is_gimple_call (stmt) && handle_gimple_call (&si))
476 /* If handle_gimple_call returns true, the iterator is
477 already pointing to the next statement. */
478 @@ -4031,13 +4006,6 @@ sprintf_dom_walker::before_dom_children (basic_block bb)
479
480 gsi_next (&si);
481 }
482 - return NULL;
483 -}
484 -
485 -void
486 -sprintf_dom_walker::after_dom_children (basic_block bb)
487 -{
488 - evrp_range_analyzer.leave (bb);
489 }
490
491 /* Execute the pass for function FUN. */
492 @@ -4047,10 +4015,9 @@ pass_sprintf_length::execute (function *fun)
493 {
494 init_target_to_host_charmap ();
495
496 - calculate_dominance_info (CDI_DOMINATORS);
497 -
498 - sprintf_dom_walker sprintf_dom_walker;
499 - sprintf_dom_walker.walk (ENTRY_BLOCK_PTR_FOR_FN (fun));
500 + basic_block bb;
501 + FOR_EACH_BB_FN (bb, fun)
502 + sprintf_walk (bb);
503
504 /* Clean up object size info. */
505 fini_object_sizes ();
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.