re PR middle-end/82123 (spurious -Wformat-overflow warning for converted vars)
authorJeff Law <law@redhat.com>
Tue, 20 Feb 2018 18:56:01 +0000 (11:56 -0700)
committerJeff Law <law@gcc.gnu.org>
Tue, 20 Feb 2018 18:56:01 +0000 (11:56 -0700)
PR middle-end/82123
PR tree-optimization/81592
PR middle-end/79257
* gimple-ssa-sprintf.c (get_int_range): Accept vr_values parameter
pass it to children as needed.
(struct directive::fmtresult): Similarly.
(struct directive::set_width): Similarly.
(struct directive::set_precision): Similarly.
(format_integer, format_directive, parse_directive): Similarly.
(format_none): Accept unnamed vr_values parameter.
(format_percent, format_floating, format_character): Similarly.
(format_string, format_plain): Similarly.

From-SVN: r257854

gcc/ChangeLog
gcc/gimple-ssa-sprintf.c

index 3dad6fe44b10cc1c08b14bc6619c280ee9a3e97e..134d5d9efda4b83cc94691b0aaad4aba7b92f28c 100644 (file)
@@ -3,6 +3,15 @@
        PR middle-end/82123
        PR tree-optimization/81592
        PR middle-end/79257
+       * gimple-ssa-sprintf.c (get_int_range): Accept vr_values parameter
+       pass it to children as needed.
+       (struct directive::fmtresult): Similarly.
+       (struct directive::set_width): Similarly.
+       (struct directive::set_precision): Similarly.
+       (format_integer, format_directive, parse_directive): Similarly.
+       (format_none): Accept unnamed vr_values parameter.
+       (format_percent, format_floating, format_character): Similarly.
+       (format_string, format_plain): Similarly.
        * gimple-ssa-sprintf.c (sprintf_dom_walker::handle_gimple_call): Query
        the EVRP range analyzer for range data rather than using global data.
        * gimple-ssa-sprintf.c: Include alloc-pool.h, vr-values.h and 
index 4b2de6d2aa45e439b4f1ce76bffdad4eadea8306..54c91320e56a230e0cb33742b452fbb3089ff6af 100644 (file)
@@ -771,7 +771,8 @@ fmtresult::type_max_digits (tree type, int base)
 }
 
 static bool
-get_int_range (tree, HOST_WIDE_INT *, HOST_WIDE_INT *, bool, HOST_WIDE_INT);
+get_int_range (tree, HOST_WIDE_INT *, HOST_WIDE_INT *, bool, HOST_WIDE_INT,
+              class vr_values *vr_values);
 
 /* Description of a format directive.  A directive is either a plain
    string or a conversion specification that starts with '%'.  */
@@ -806,7 +807,7 @@ struct directive
 
   /* Format conversion function that given a directive and an argument
      returns the formatting result.  */
-  fmtresult (*fmtfunc) (const directive &, tree);
+  fmtresult (*fmtfunc) (const directive &, tree, vr_values *);
 
   /* Return True when a the format flag CHR has been used.  */
   bool get_flag (char chr) const
@@ -843,9 +844,9 @@ struct directive
      or 0, whichever is greater.  For a non-constant ARG in some range
      set width to its range adjusting each bound to -1 if it's less.
      For an indeterminate ARG set width to [0, INT_MAX].  */
-  void set_width (tree arg)
+  void set_width (tree arg, vr_values *vr_values)
   {
-    get_int_range (arg, width, width + 1, true, 0);
+    get_int_range (arg, width, width + 1, true, 0, vr_values);
   }
 
   /* Set both bounds of the precision range to VAL.  */
@@ -859,9 +860,9 @@ struct directive
      or -1 whichever is greater.  For a non-constant ARG in some range
      set precision to its range adjusting each bound to -1 if it's less.
      For an indeterminate ARG set precision to [-1, INT_MAX].  */
-  void set_precision (tree arg)
+  void set_precision (tree arg, vr_values *vr_values)
   {
-    get_int_range (arg, prec, prec + 1, false, -1);
+    get_int_range (arg, prec, prec + 1, false, -1, vr_values);
   }
 
   /* Return true if both width and precision are known to be
@@ -1042,7 +1043,7 @@ struct sprintf_dom_walker::call_info
 /* Return the result of formatting a no-op directive (such as '%n').  */
 
 static fmtresult
-format_none (const directive &, tree)
+format_none (const directive &, tree, vr_values *)
 {
   fmtresult res (0);
   return res;
@@ -1051,7 +1052,7 @@ format_none (const directive &, tree)
 /* Return the result of formatting the '%%' directive.  */
 
 static fmtresult
-format_percent (const directive &, tree)
+format_percent (const directive &, tree, vr_values *)
 {
   fmtresult res (1);
   return res;
@@ -1108,7 +1109,8 @@ build_intmax_type_nodes (tree *pintmax, tree *puintmax)
 
 static bool
 get_int_range (tree arg, HOST_WIDE_INT *pmin, HOST_WIDE_INT *pmax,
-              bool absolute, HOST_WIDE_INT negbound)
+              bool absolute, HOST_WIDE_INT negbound,
+              class vr_values *vr_values)
 {
   /* The type of the result.  */
   const_tree type = integer_type_node;
@@ -1179,7 +1181,8 @@ get_int_range (tree arg, HOST_WIDE_INT *pmin, HOST_WIDE_INT *pmax,
       /* Handle an argument with an unknown range as if none had been
         provided.  */
       if (unknown)
-       return get_int_range (NULL_TREE, pmin, pmax, absolute, negbound);
+       return get_int_range (NULL_TREE, pmin, pmax, absolute,
+                             negbound, vr_values);
     }
 
   /* Adjust each bound as specified by ABSOLUTE and NEGBOUND.  */
@@ -1264,7 +1267,7 @@ adjust_range_for_overflow (tree dirtype, tree *argmin, tree *argmax)
    used when the directive argument or its value isn't known.  */
 
 static fmtresult
-format_integer (const directive &dir, tree arg)
+format_integer (const directive &dir, tree arg, vr_values *vr_values)
 {
   tree intmax_type_node;
   tree uintmax_type_node;
@@ -1482,7 +1485,7 @@ format_integer (const directive &dir, tree arg)
              if (code == INTEGER_CST)
                {
                  arg = gimple_assign_rhs1 (def);
-                 return format_integer (dir, arg);
+                 return format_integer (dir, arg, vr_values);
                }
 
              if (code == NOP_EXPR)
@@ -1527,16 +1530,16 @@ format_integer (const directive &dir, tree arg)
       /* For unsigned conversions/directives or signed when
         the minimum is positive, use the minimum and maximum to compute
         the shortest and longest output, respectively.  */
-      res.range.min = format_integer (dir, argmin).range.min;
-      res.range.max = format_integer (dir, argmax).range.max;
+      res.range.min = format_integer (dir, argmin, vr_values).range.min;
+      res.range.max = format_integer (dir, argmax, vr_values).range.max;
     }
   else if (tree_int_cst_sgn (argmax) < 0)
     {
       /* For signed conversions/directives if maximum is negative,
         use the minimum as the longest output and maximum as the
         shortest output.  */
-      res.range.min = format_integer (dir, argmax).range.min;
-      res.range.max = format_integer (dir, argmin).range.max;
+      res.range.min = format_integer (dir, argmax, vr_values).range.min;
+      res.range.max = format_integer (dir, argmin, vr_values).range.max;
     }
   else
     {
@@ -1544,9 +1547,12 @@ format_integer (const directive &dir, tree arg)
         as the shortest output and for the longest output compute the
         length of the output of both minimum and maximum and pick the
         longer.  */
-      unsigned HOST_WIDE_INT max1 = format_integer (dir, argmin).range.max;
-      unsigned HOST_WIDE_INT max2 = format_integer (dir, argmax).range.max;
-      res.range.min = format_integer (dir, integer_zero_node).range.min;
+      unsigned HOST_WIDE_INT max1
+       = format_integer (dir, argmin, vr_values).range.max;
+      unsigned HOST_WIDE_INT max2
+       = format_integer (dir, argmax, vr_values).range.max;
+      res.range.min
+       = format_integer (dir, integer_zero_node, vr_values).range.min;
       res.range.max = MAX (max1, max2);
     }
 
@@ -1887,7 +1893,7 @@ format_floating (const directive &dir, const HOST_WIDE_INT prec[2])
    ARG.  */
 
 static fmtresult
-format_floating (const directive &dir, tree arg)
+format_floating (const directive &dir, tree arg, vr_values *)
 {
   HOST_WIDE_INT prec[] = { dir.prec[0], dir.prec[1] };
   tree type = (dir.modifier == FMT_LEN_L || dir.modifier == FMT_LEN_ll
@@ -2127,7 +2133,7 @@ get_string_length (tree str)
    vsprinf).  */
 
 static fmtresult
-format_character (const directive &dir, tree arg)
+format_character (const directive &dir, tree arg, vr_values *vr_values)
 {
   fmtresult res;
 
@@ -2139,7 +2145,7 @@ format_character (const directive &dir, tree arg)
       res.range.min = 0;
 
       HOST_WIDE_INT min, max;
-      if (get_int_range (arg, &min, &max, false, 0))
+      if (get_int_range (arg, &min, &max, false, 0, vr_values))
        {
          if (min == 0 && max == 0)
            {
@@ -2192,7 +2198,7 @@ format_character (const directive &dir, tree arg)
    vsprinf).  */
 
 static fmtresult
-format_string (const directive &dir, tree arg)
+format_string (const directive &dir, tree arg, vr_values *)
 {
   fmtresult res;
 
@@ -2353,7 +2359,7 @@ format_string (const directive &dir, tree arg)
 /* Format plain string (part of the format string itself).  */
 
 static fmtresult
-format_plain (const directive &dir, tree)
+format_plain (const directive &dir, tree, vr_values *)
 {
   fmtresult res (dir.len);
   return res;
@@ -2734,7 +2740,8 @@ maybe_warn (substring_loc &dirloc, location_t argloc,
 
 static bool
 format_directive (const sprintf_dom_walker::call_info &info,
-                 format_result *res, const directive &dir)
+                 format_result *res, const directive &dir,
+                 class vr_values *vr_values)
 {
   /* Offset of the beginning of the directive from the beginning
      of the format string.  */
@@ -2759,7 +2766,7 @@ format_directive (const sprintf_dom_walker::call_info &info,
     return false;
 
   /* Compute the range of lengths of the formatted output.  */
-  fmtresult fmtres = dir.fmtfunc (dir, dir.arg);
+  fmtresult fmtres = dir.fmtfunc (dir, dir.arg, vr_values);
 
   /* Record whether the output of all directives is known to be
      bounded by some maximum, implying that their arguments are
@@ -3025,7 +3032,8 @@ format_directive (const sprintf_dom_walker::call_info &info,
 static size_t
 parse_directive (sprintf_dom_walker::call_info &info,
                 directive &dir, format_result *res,
-                const char *str, unsigned *argno)
+                const char *str, unsigned *argno,
+                vr_values *vr_values)
 {
   const char *pcnt = strchr (str, target_percent);
   dir.beg = str;
@@ -3343,7 +3351,7 @@ parse_directive (sprintf_dom_walker::call_info &info,
   if (star_width)
     {
       if (INTEGRAL_TYPE_P (TREE_TYPE (star_width)))
-       dir.set_width (star_width);
+       dir.set_width (star_width, vr_values);
       else
        {
          /* Width specified by a va_list takes on the range [0, -INT_MIN]
@@ -3376,7 +3384,7 @@ parse_directive (sprintf_dom_walker::call_info &info,
   if (star_precision)
     {
       if (INTEGRAL_TYPE_P (TREE_TYPE (star_precision)))
-       dir.set_precision (star_precision);
+       dir.set_precision (star_precision, vr_values);
       else
        {
          /* Precision specified by a va_list takes on the range [-1, INT_MAX]
@@ -3498,10 +3506,12 @@ sprintf_dom_walker::compute_format_length (call_info &info,
       directive dir = directive ();
       dir.dirno = dirno;
 
-      size_t n = parse_directive (info, dir, res, pf, &argno);
+      size_t n = parse_directive (info, dir, res, pf, &argno,
+                                 evrp_range_analyzer.get_vr_values ());
 
       /* Return failure if the format function fails.  */
-      if (!format_directive (info, res, dir))
+      if (!format_directive (info, res, dir,
+                            evrp_range_analyzer.get_vr_values ()))
        return false;
 
       /* Return success the directive is zero bytes long and it's