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.