[PATCH 3/4] - Change sprintf to use new get_range_strlen overload

Martin Sebor msebor@gmail.com
Tue Oct 2 16:46:00 GMT 2018


[3/4] - Change sprintf to use new get_range_strlen overload

This change makes use of the new get_range_strlen() overload
in gimple-ssa-sprintf.c.  This necessitated a few changes to
the API but also enabled the removal of the flexarray member
from strlen_data_t.

This also patch restores the bool return value for the public
get_strlen_range function but with a different meaning (to
indicate whether the computed range is suitable as is to rely
on for optimization, rather than whether the argument may
refer to a flexible array member).

The changes to gimple-ssa-sprintf.c involve more indentation
adjustments than new functionality so to make the review easier
I attach gcc-99999-3-gimple-ssa-sprintf.c.diff-b with the white
space changes stripped.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: gcc-99999-3.diff
Type: text/x-patch
Size: 19435 bytes
Desc: not available
URL: <http://gcc.gnu.org/pipermail/gcc-patches/attachments/20181002/5668cdb2/attachment.bin>
-------------- next part --------------
diff --git a/gcc/gimple-ssa-sprintf.c b/gcc/gimple-ssa-sprintf.c
index 0ce016b..51f8826 100644
--- a/gcc/gimple-ssa-sprintf.c
+++ b/gcc/gimple-ssa-sprintf.c
@@ -2004,24 +2004,37 @@ get_string_length (tree str, unsigned eltsize)
   /* Determine the length of the shortest and longest string referenced
      by STR.  Strings of unknown lengths are bounded by the sizes of
      arrays that subexpressions of STR may refer to.  Pointers that
-     aren't known to point any such arrays result in LENRANGE[1] set
-     to SIZE_MAX.  */
-  tree lenrange[2];
-  bool flexarray = get_range_strlen (str, lenrange, eltsize,
-				     /* strict = */ false);
+     aren't known to point any such arrays result in LENDATA.MAXLEN
+     set to SIZE_MAX.  */
+  strlen_data_t lendata (eltsize);
+  get_range_strlen (str, &lendata);
+
+  /* Return the default result when nothing is known about the string. */
+  if (integer_all_onesp (lendata.maxsize)
+      && integer_all_onesp (lendata.maxlen))
+    return fmtresult ();
 
-  if (lenrange [0] || lenrange [1])
-    {
   HOST_WIDE_INT min
-	= (tree_fits_uhwi_p (lenrange[0])
-	   ? tree_to_uhwi (lenrange[0])
+    = (tree_fits_uhwi_p (lendata.minlen)
+       ? tree_to_uhwi (lendata.minlen)
        : 0);
 
   HOST_WIDE_INT max
-	= (tree_fits_uhwi_p (lenrange[1])
-	   ? tree_to_uhwi (lenrange[1])
+    = (tree_fits_uhwi_p (lendata.maxsize)
+       ? tree_to_uhwi (lendata.maxsize)
        : HOST_WIDE_INT_M1U);
 
+  const bool unbounded = integer_all_onesp (lendata.maxlen);
+
+  /* Set the max/likely counters to unbounded when a minimum is known
+     but the maximum length isn't bounded.  This implies that STR is
+     a conditional expression involving a string of known length and
+     and an expression of unknown/unbounded length.  */
+  if (min
+      && (unsigned HOST_WIDE_INT)min < HOST_WIDE_INT_M1U
+      && unbounded)
+    max = HOST_WIDE_INT_M1U;
+
   /* get_range_strlen() returns the target value of SIZE_MAX for
      strings of unknown length.  Bump it up to HOST_WIDE_INT_M1U
      which may be bigger.  */
@@ -2055,12 +2068,12 @@ get_string_length (tree str, unsigned eltsize)
      of an array at the end of a struct assume that it's longer than
      the array bound says it is in case it's used as a poor man's
      flexible array member, such as in struct S { char a[4]; };  */
-      res.range.unlikely = flexarray ? HOST_WIDE_INT_MAX : res.range.max;
+  if (/* lendata.flexarray || */ unbounded)
+    res.range.unlikely = HOST_WIDE_INT_MAX;
+  else
+    res.range.unlikely = res.range.max;
 
   return res;
-    }
-
-  return fmtresult ();
 }
 
 /* Return the minimum and maximum number of characters formatted
@@ -2288,6 +2301,8 @@ format_string (const directive &dir, tree arg, vr_values *)
 	  if ((unsigned HOST_WIDE_INT)dir.prec[1] < slen.range.max)
 	    res.range.max = dir.prec[1];
 	  res.range.likely = dir.prec[1] ? warn_level > 1 : 0;
+	  if ((unsigned HOST_WIDE_INT)dir.prec[1] < slen.range.unlikely)
+	    res.range.unlikely = dir.prec[1];
 	}
       else if (slen.range.min >= target_int_max ())
 	{
@@ -2297,6 +2312,7 @@ format_string (const directive &dir, tree arg, vr_values *)
 	     empty, while at level 1 they are assumed to be one byte
 	     long.  */
 	  res.range.likely = warn_level > 1;
+	  res.range.unlikely = HOST_WIDE_INT_MAX;
 	}
       else
 	{
@@ -2306,8 +2322,6 @@ format_string (const directive &dir, tree arg, vr_values *)
 	  if (res.range.likely >= target_int_max ())
 	    res.range.likely = warn_level > 1;
 	}
-
-      res.range.unlikely = res.range.max;
     }
 
   /* Bump up the byte counters if WIDTH is greater.  */


More information about the Gcc-patches mailing list