[committed] Add new fields to c_strlen_data structure, rename field access

Jeff Law law@redhat.com
Sun Dec 23 16:23:00 GMT 2018


This is probably a good place to stop for today and let the testers
catch up.

This patch introduces new fields into the c_strlen_data structure.
They're mostly unused at this point.  The data structure shouldn't
change in subsequent patches.  The old "len" field accesses are changed
to "minlen" which allows the existing code to work with the new data
structure.

Bootstrapped and regression tested.  Installing on the trunk.

Jeff
-------------- next part --------------
commit 6f7fa01feb7087acd4e11d22efb3b1a4d966652d
Author: law <law@138bc75d-0d04-0410-961f-82ee72b054a4>
Date:   Sun Dec 23 16:00:45 2018 +0000

            * builtins.h (c_strlen_data): Add new fields and comments.
            * builtins.c (unterminated_array): Change field reference from
            "len" to "minlen" in c_strlen_data instance.
            * gimple-fold.c (get_range_strlen): Likewise.
            * gimple-ssa-sprintf.c (get_string_length): Likewise.
    
    git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@267378 138bc75d-0d04-0410-961f-82ee72b054a4

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f1f9d70f25b..cd2a294c583 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,6 +1,12 @@
 2018-12-23  Martin Sebor  <msebor@redhat.com>
 	    Jeff Law  <law@redhat.com>
 
+	* builtins.h (c_strlen_data): Add new fields and comments.
+	* builtins.c (unterminated_array): Change field reference from
+	"len" to "minlen" in c_strlen_data instance.
+	* gimple-fold.c (get_range_strlen): Likewise.
+	* gimple-ssa-sprintf.c (get_string_length): Likewise.
+
 	* builtins.c (unterminated_array): Rename "data" to "lendata".  Fix
 	a few comments.
 	(expand_builtin_strnlen, expand_builtin_stpcpy_1): Likewise.
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 0eb3df9ccc1..b56577e450c 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -577,11 +577,11 @@ unterminated_array (tree exp, tree *size /* = NULL */, bool *exact /* = NULL */)
      structure if EXP references a unterminated array.  */
   c_strlen_data lendata = { };
   tree len = c_strlen (exp, 1, &lendata);
-  if (len == NULL_TREE && lendata.len && lendata.decl)
+  if (len == NULL_TREE && lendata.minlen && lendata.decl)
      {
        if (size)
 	{
-	  len = lendata.len;
+	  len = lendata.minlen;
 	  if (lendata.off)
 	    {
 	      /* Constant offsets are already accounted for in LENDATA.MINLEN,
@@ -720,7 +720,7 @@ c_strlen (tree src, int only_value, c_strlen_data *data, unsigned eltsize)
 	{
 	  data->decl = decl;
 	  data->off = byteoff;
-	  data->len = ssize_int (len);
+	  data->minlen = ssize_int (len);
 	  return NULL_TREE;
 	}
 
@@ -794,7 +794,7 @@ c_strlen (tree src, int only_value, c_strlen_data *data, unsigned eltsize)
     {
       data->decl = decl;
       data->off = byteoff;
-      data->len = ssize_int (len);
+      data->minlen = ssize_int (len);
       return NULL_TREE;
     }
 
diff --git a/gcc/builtins.h b/gcc/builtins.h
index cf4f9b1b264..472a86d9ad0 100644
--- a/gcc/builtins.h
+++ b/gcc/builtins.h
@@ -57,10 +57,48 @@ extern bool get_pointer_alignment_1 (tree, unsigned int *,
 				     unsigned HOST_WIDE_INT *);
 extern unsigned int get_pointer_alignment (tree);
 extern unsigned string_length (const void*, unsigned, unsigned);
+
 struct c_strlen_data
 {
+  /* [MINLEN, MAXBOUND, MAXLEN] is a range describing the length of
+     one or more strings of possibly unknown length.  For a single
+     string of known length the range is a constant where
+     MINLEN == MAXBOUND == MAXLEN holds.
+     For other strings, MINLEN is the length of the shortest known
+     string.  MAXBOUND is the length of a string that could be stored
+     in the largest array referenced by the expression.  MAXLEN is
+     the length of the longest sequence of non-zero bytes
+     in an object referenced by the expression.  For such strings,
+     MINLEN <= MAXBOUND <= MAXLEN holds.  For example, given:
+       struct A { char a[7], b[]; };
+       extern struct A *p;
+       n = strlen (p->a);
+     the computed range will be [0, 6, ALL_ONES].
+     However, for a conditional expression involving a string
+     of known length and an array of unknown bound such as
+       n = strlen (i ? p->b : "123");
+     the range will be [3, 3, ALL_ONES].
+     MINLEN != 0 && MAXLEN == ALL_ONES indicates that MINLEN is
+     the length of the shortest known string and implies that
+     the shortest possible string referenced by the expression may
+     actually be the empty string.  This distinction is useful for
+     diagnostics.  get_range_strlen() return value distinguishes
+     between these two cases.
+     As the tighter (and more optimistic) bound, MAXBOUND is suitable
+     for diagnostics but not for optimization.
+     As the more conservative bound, MAXLEN is intended to be used
+     for optimization.  */
+  tree minlen;
+  tree maxlen;
+  tree maxbound;
+  /* When non-null, NONSTR refers to the declaration known to store
+     an unterminated constant character array, as in:
+     const char s[] = { 'a', 'b', 'c' };
+     It is used to diagnose uses of such arrays in functions such as
+     strlen() that expect a nul-terminated string as an argument.  */
   tree decl;
-  tree len;
+  /* Non-constant offset from the beginning of a string not accounted
+     for in the length range.  Used to improve diagnostics.  */
   tree off;
 };
 
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index 0ba15149890..b1dd4416567 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -1343,8 +1343,8 @@ get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
 	  if (!val && lendata.decl)
 	    {
 	      *nonstr = lendata.decl;
-	      *minlen = lendata.len;
-	      *maxlen = lendata.len;
+	      *minlen = lendata.minlen;
+	      *maxlen = lendata.minlen;
 	      return type == 0 ? false : true;
 	    }
 	}
diff --git a/gcc/gimple-ssa-sprintf.c b/gcc/gimple-ssa-sprintf.c
index d6278305fc4..8284c76b0f7 100644
--- a/gcc/gimple-ssa-sprintf.c
+++ b/gcc/gimple-ssa-sprintf.c
@@ -2015,12 +2015,12 @@ get_string_length (tree str, unsigned eltsize)
     }
   else if (!slen
 	   && data.decl
-	   && data.len
-	   && TREE_CODE (data.len) == INTEGER_CST)
+	   && data.minlen
+	   && TREE_CODE (data.minlen) == INTEGER_CST)
     {
       /* STR was not properly NUL terminated, but we have
 	 length information about the unterminated string.  */
-      fmtresult res (tree_to_shwi (data.len));
+      fmtresult res (tree_to_shwi (data.minlen));
       res.nonstr = data.decl;
       return res;
     }


More information about the Gcc-patches mailing list