This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[committed] Replace type/fuzzy arguments with a single enum


This is another chunk of Martin's work that I've extracted.  It removes
the "type" and "fuzzy" parameters we pass to get_range_strlen and
replaces them with a strlen_range_kind enum.  Mostly this cleans up the
API and avoids the possibility of bogus combinations of "type" and "fuzzy".

It has one enum value not in Martin's changes.  It's temporary until the
rest of Martin's work goes in.  Essentially it's what used to be fuzzy2
and will be handled by recording two ranges in the later hunks from
Martin.  By introducing it now we can drop in a significant chunk of the
API changes without affecting behavior which makes the final behavior
changing patch easier to manage.

Bootstrapped and regression tested on x86_64-linux-gnu.  Installing on
the trunk.   My testers will churn on this over the holiday on the other
targets.

Jeff
commit 6454350352aa678b61caa3bc65e463bd1695e7fa
Author: Jeff Law <law@torsion.usersys.redhat.com>
Date:   Fri Dec 21 14:23:49 2018 -0500

            * gimple-fold.c (strlen_range_kind): New enum.
            (get_range_strlen): Update signature to use strlen_range_kind
            instead of type+fuzzy.
            (get_range_strlen_tree): Update signature to use
            strlen_range_kind instead of type+fuzzy.  Pass rkind down to
            get_range_strlen.  Check the rkind enum value instead of
            type+fuzzy.
            (get_range_strlen): Similarly.
            (get_maxval_strlen): Update signature to make NONSTR argument have
            a default value and make static.  Add asserts to ensure sanity of
            arguments.  Update calls to get_range_strlen.
            (gimple_fold_builtin_strcpy): Update calls to get_maxval_strlen.
            (gimple_fold_builtin_strcat, gimple_fold_builtin_fputs): Similarly.
            (gimple_fold_builtin_memory_chk): Similarly.
            (gimple_fold_builtin_stxcpy_chk): Similarly.
            (gimple_fold_builtin_snprintf_chk): Similarly.
            (gimple_fold_builtin_sprintf, gimple_fold_builtin_snprintf): Similarly.
            * gimple-fold.h (get_maxval_strlen): Delete prototype.

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index bb02095e42f..1ee865e1de8 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,25 @@
+2018-12-30  Martin Sebor  <msebor@redhat.com>
+	    Jeff Law  <law@redhat.com>
+
+	* gimple-fold.c (strlen_range_kind): New enum.
+	(get_range_strlen): Update signature to use strlen_range_kind
+	instead of type+fuzzy.
+	(get_range_strlen_tree): Update signature to use
+	strlen_range_kind instead of type+fuzzy.  Pass rkind down to
+	get_range_strlen.  Check the rkind enum value instead of
+	type+fuzzy.
+	(get_range_strlen): Similarly.
+	(get_maxval_strlen): Update signature to make NONSTR argument have
+	a default value and make static.  Add asserts to ensure sanity of
+	arguments.  Update calls to get_range_strlen.
+	(gimple_fold_builtin_strcpy): Update calls to get_maxval_strlen.
+	(gimple_fold_builtin_strcat, gimple_fold_builtin_fputs): Similarly.
+	(gimple_fold_builtin_memory_chk): Similarly.
+	(gimple_fold_builtin_stxcpy_chk): Similarly.
+	(gimple_fold_builtin_snprintf_chk): Similarly.
+	(gimple_fold_builtin_sprintf, gimple_fold_builtin_snprintf): Similarly.
+	* gimple-fold.h (get_maxval_strlen): Delete prototype.
+
 2018-12-29  Jozef Lawrynowicz  <jozef.l@mittosystems.com>
 
 	* config/msp430/msp430.c (msp430_attr): Warn when the critical and
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index 4f84f0c0cc3..76fa328703c 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -66,8 +66,25 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-vector-builder.h"
 #include "tree-ssa-strlen.h"
 
-static bool get_range_strlen (tree, tree[2], bitmap *, int,
-		  int, bool *, unsigned, tree *);
+enum strlen_range_kind {
+  /* Compute the exact constant string length.  */
+  SRK_STRLEN,
+  /* Compute the maximum constant string length.  */
+  SRK_STRLENMAX,
+  /* Compute a range of string lengths bounded by object sizes.  When
+     the length of a string cannot be determined, consider as the upper
+     bound the size of the enclosing object the string may be a member
+     or element of.  Also determine the size of the largest character
+     array the string may refer to.  */
+  SRK_LENRANGE,
+  /* Temporary until the rest of Martin's strlen range work is integrated.  */
+  SRK_LENRANGE_2,
+  /* Determine the integer value of the argument (not string length).  */
+  SRK_INT_VALUE
+};
+
+static bool get_range_strlen (tree, tree[2], bitmap *, strlen_range_kind,
+		  bool *, unsigned, tree *);
 
 /* Return true when DECL can be referenced from current unit.
    FROM_DECL (if non-null) specify constructor of variable DECL was taken from.
@@ -1264,8 +1281,9 @@ gimple_fold_builtin_memset (gimple_stmt_iterator *gsi, tree c, tree len)
 /* Helper of get_range_strlen for ARG that is not an SSA_NAME.  */
 
 static bool
-get_range_strlen_tree (tree arg, tree length[2], bitmap *visited, int type,
-		       int fuzzy, bool *flexp, unsigned eltsize, tree *nonstr)
+get_range_strlen_tree (tree arg, tree length[2], bitmap *visited,
+		       strlen_range_kind rkind,
+		       bool *flexp, unsigned eltsize, tree *nonstr)
 {
   gcc_assert (TREE_CODE (arg) != SSA_NAME);
  
@@ -1287,10 +1305,11 @@ get_range_strlen_tree (tree arg, tree length[2], bitmap *visited, int type,
 	  if (TREE_CODE (aop0) == INDIRECT_REF
 	      && TREE_CODE (TREE_OPERAND (aop0, 0)) == SSA_NAME)
 	    return get_range_strlen (TREE_OPERAND (aop0, 0), length,
-				     visited, type, fuzzy, flexp,
+				     visited, rkind, flexp,
 				     eltsize, nonstr);
 	}
-      else if (TREE_CODE (TREE_OPERAND (op, 0)) == COMPONENT_REF && fuzzy)
+      else if (TREE_CODE (TREE_OPERAND (op, 0)) == COMPONENT_REF
+	       && (rkind == SRK_LENRANGE || rkind == SRK_LENRANGE_2))
 	{
 	  /* Fail if an array is the last member of a struct object
 	     since it could be treated as a (fake) flexible array
@@ -1308,7 +1327,7 @@ get_range_strlen_tree (tree arg, tree length[2], bitmap *visited, int type,
 	}
     }
 
-  if (type == 2)
+  if (rkind == SRK_INT_VALUE)
     {
       /* We are computing the maximum value (not string length).  */
       val = arg;
@@ -1328,15 +1347,15 @@ get_range_strlen_tree (tree arg, tree length[2], bitmap *visited, int type,
 	  *nonstr = lendata.decl;
 	  *minlen = lendata.minlen;
 	  *maxlen = lendata.minlen;
-	  return type == 0 ? false : true;
+	  return rkind == SRK_STRLEN ? false : true;
 	}
     }
 
-  if (!val && fuzzy)
+  if (!val && (rkind == SRK_LENRANGE || rkind == SRK_LENRANGE_2))
     {
       if (TREE_CODE (arg) == ADDR_EXPR)
 	return get_range_strlen (TREE_OPERAND (arg, 0), length,
-				 visited, type, fuzzy, flexp,
+				 visited, rkind, flexp,
 				 eltsize, nonstr);
 
       if (TREE_CODE (arg) == ARRAY_REF)
@@ -1435,7 +1454,7 @@ get_range_strlen_tree (tree arg, tree length[2], bitmap *visited, int type,
 
   /* Adjust the lower bound on the string length as necessary.  */
   if (!*minlen
-      || (type > 0
+      || (rkind != SRK_STRLEN
 	  && TREE_CODE (*minlen) == INTEGER_CST
 	  && TREE_CODE (val) == INTEGER_CST
 	  && tree_int_cst_lt (val, *minlen)))
@@ -1445,7 +1464,7 @@ get_range_strlen_tree (tree arg, tree length[2], bitmap *visited, int type,
     {
       /* Adjust the more conservative bound if possible/necessary
 	 and fail otherwise.  */
-      if (type > 0)
+      if (rkind != SRK_STRLEN)
 	{
 	  if (TREE_CODE (*maxlen) != INTEGER_CST
 	      || TREE_CODE (val) != INTEGER_CST)
@@ -1473,29 +1492,21 @@ get_range_strlen_tree (tree arg, tree length[2], bitmap *visited, int type,
    TYPE == 0, if LENGTH[1] is not equal to the length we determine or
    if we are unable to determine the length or value, return false.
    VISITED is a bitmap of visited variables.
-   TYPE is 0 if string length should be obtained, 1 for maximum string
-   length and 2 for maximum value ARG can have.
-   When FUZZY is non-zero and the length of a string cannot be determined,
-   the function instead considers as the maximum possible length the
-   size of a character array it may refer to.  If FUZZY is 2, it will handle
-   PHIs and COND_EXPRs optimistically, if we can determine string length
-   minimum and maximum, it will use the minimum from the ones where it
-   can be determined.
-   Set *FLEXP to true if the range of the string lengths has been
-   obtained from the upper bound of an array at the end of a struct.
-   Such an array may hold a string that's longer than its upper bound
-   due to it being used as a poor-man's flexible array member.
-   Pass NONSTR through to children.
-   ELTSIZE is 1 for normal single byte character strings, and 2 or
-   4 for wide characer strings.  ELTSIZE is by default 1.  */
+   RKIND determines the kind of value or range to obtain (see
+   strlen_range_kind).
+   Set PDATA->DECL if ARG refers to an unterminated constant array.
+   On input, set ELTSIZE to 1 for normal single byte character strings,
+   and either 2 or 4 for wide characer strings (the size of wchar_t).
+   Return true if *PDATA was successfully populated and false otherwise.  */
 
 static bool
-get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
-		  int fuzzy, bool *flexp, unsigned eltsize, tree *nonstr)
+get_range_strlen (tree arg, tree length[2], bitmap *visited,
+		  strlen_range_kind rkind,
+		  bool *flexp, unsigned eltsize, tree *nonstr)
 {
 
   if (TREE_CODE (arg) != SSA_NAME)
-    return get_range_strlen_tree (arg, length, visited, type, fuzzy, flexp,
+    return get_range_strlen_tree (arg, length, visited, rkind, flexp,
 				  eltsize, nonstr);
 
   /* If ARG is registered for SSA update we cannot look at its defining
@@ -1518,14 +1529,14 @@ get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
   switch (gimple_code (def_stmt))
     {
       case GIMPLE_ASSIGN:
-        /* The RHS of the statement defining VAR must either have a
-           constant length or come from another SSA_NAME with a constant
-           length.  */
+	/* The RHS of the statement defining VAR must either have a
+	   constant length or come from another SSA_NAME with a constant
+	   length.  */
         if (gimple_assign_single_p (def_stmt)
             || gimple_assign_unary_nop_p (def_stmt))
           {
-            tree rhs = gimple_assign_rhs1 (def_stmt);
-	    return get_range_strlen (rhs, length, visited, type, fuzzy, flexp,
+	    tree rhs = gimple_assign_rhs1 (def_stmt);
+	    return get_range_strlen (rhs, length, visited, rkind, flexp,
 				     eltsize, nonstr);
           }
 	else if (gimple_assign_rhs_code (def_stmt) == COND_EXPR)
@@ -1534,10 +1545,10 @@ get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
 			    gimple_assign_rhs3 (def_stmt) };
 
 	    for (unsigned int i = 0; i < 2; i++)
-	      if (!get_range_strlen (ops[i], length, visited, type, fuzzy,
+	      if (!get_range_strlen (ops[i], length, visited, rkind,
 				     flexp, eltsize, nonstr))
 		{
-		  if (fuzzy == 2)
+		  if (rkind == SRK_LENRANGE_2)
 		    *maxlen = build_all_ones_cst (size_type_node);
 		  else
 		    return false;
@@ -1547,8 +1558,8 @@ get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
         return false;
 
       case GIMPLE_PHI:
-	/* All the arguments of the PHI node must have the same constant
-	   length.  */
+	/* Unless RKIND == SRK_LENRANGE, all arguments of the PHI node
+	   must have a constant length.  */
 	for (unsigned i = 0; i < gimple_phi_num_args (def_stmt); i++)
           {
             tree arg = gimple_phi_arg (def_stmt, i)->def;
@@ -1562,10 +1573,10 @@ get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
             if (arg == gimple_phi_result (def_stmt))
               continue;
 
-	    if (!get_range_strlen (arg, length, visited, type, fuzzy, flexp,
+	    if (!get_range_strlen (arg, length, visited, rkind, flexp,
 				   eltsize, nonstr))
 	      {
-		if (fuzzy == 2)
+		if (rkind == SRK_LENRANGE_2)
 		  *maxlen = build_all_ones_cst (size_type_node);
 		else
 		  return false;
@@ -1617,7 +1628,8 @@ get_range_strlen (tree arg, tree minmaxlen[2], unsigned eltsize,
   *nonstr = NULL_TREE;
 
   bool flexarray = false;
-  if (!get_range_strlen (arg, minmaxlen, &visited, 1, strict ? 1 : 2,
+  if (!get_range_strlen (arg, minmaxlen, &visited,
+			 strict ? SRK_LENRANGE : SRK_LENRANGE_2,
 			 &flexarray, eltsize, nonstr))
     {
       minmaxlen[0] = NULL_TREE;
@@ -1638,16 +1650,22 @@ get_range_strlen (tree arg, tree minmaxlen[2], unsigned eltsize,
    unterminated strings, then bubble up the offending DECL and
    return the maximum size.  Otherwise return NULL.  */
 
-tree
-get_maxval_strlen (tree arg, int type, tree *nonstr /* = NULL */)
+static tree
+get_maxval_strlen (tree arg, strlen_range_kind rkind, tree *nonstr = NULL)
 {
+  /* A non-null NONSTR is meaningless when determining the maximum
+     value of an integer ARG.  */
+  gcc_assert (rkind != SRK_INT_VALUE || nonstr == NULL);
+  /* ARG must have an integral type when RKIND says so.  */
+  gcc_assert (rkind != SRK_INT_VALUE || INTEGRAL_TYPE_P (TREE_TYPE (arg)));
+
   bitmap visited = NULL;
   tree len[2] = { NULL_TREE, NULL_TREE };
 
   bool dummy;
   /* Set to non-null if ARG refers to an untermianted array.  */
   tree mynonstr = NULL_TREE;
-  if (!get_range_strlen (arg, len, &visited, type, 0, &dummy, 1, &mynonstr))
+  if (!get_range_strlen (arg, len, &visited, rkind, &dummy, 1, &mynonstr))
     len[1] = NULL_TREE;
   if (visited)
     BITMAP_FREE (visited);
@@ -1707,7 +1725,7 @@ gimple_fold_builtin_strcpy (gimple_stmt_iterator *gsi,
 
   /* Set to non-null if ARG refers to an unterminated array.  */
   tree nonstr = NULL;
-  tree len = get_maxval_strlen (src, 0, &nonstr);
+  tree len = get_maxval_strlen (src, SRK_STRLEN, &nonstr);
 
   if (nonstr)
     {
@@ -1753,7 +1771,7 @@ gimple_fold_builtin_strncpy (gimple_stmt_iterator *gsi,
 
 	  /* Warn about the lack of nul termination: the result is not
 	     a (nul-terminated) string.  */
-	  tree slen = get_maxval_strlen (src, 0);
+	  tree slen = get_maxval_strlen (src, SRK_STRLEN);
 	  if (slen && !integer_zerop (slen))
 	    warning_at (loc, OPT_Wstringop_truncation,
 			"%G%qD destination unchanged after copying no bytes "
@@ -1775,7 +1793,7 @@ gimple_fold_builtin_strncpy (gimple_stmt_iterator *gsi,
     return false;
 
   /* Now, we must be passed a constant src ptr parameter.  */
-  tree slen = get_maxval_strlen (src, 0);
+  tree slen = get_maxval_strlen (src, SRK_STRLEN);
   if (!slen || TREE_CODE (slen) != INTEGER_CST)
     return false;
 
@@ -1997,7 +2015,7 @@ gimple_fold_builtin_strcat (gimple_stmt_iterator *gsi, tree dst, tree src)
 
   /* If the length of the source string isn't computable don't
      split strcat into strlen and memcpy.  */
-  tree len = get_maxval_strlen (src, 0);
+  tree len = get_maxval_strlen (src, SRK_STRLEN);
   if (! len)
     return false;
 
@@ -2513,7 +2531,7 @@ gimple_fold_builtin_fputs (gimple_stmt_iterator *gsi,
 
   /* Get the length of the string passed to fputs.  If the length
      can't be determined, punt.  */
-  tree len = get_maxval_strlen (arg0, 0);
+  tree len = get_maxval_strlen (arg0, SRK_STRLEN);
   if (!len
       || TREE_CODE (len) != INTEGER_CST)
     return false;
@@ -2601,7 +2619,7 @@ gimple_fold_builtin_memory_chk (gimple_stmt_iterator *gsi,
   if (! tree_fits_uhwi_p (size))
     return false;
 
-  tree maxlen = get_maxval_strlen (len, 2);
+  tree maxlen = get_maxval_strlen (len, SRK_INT_VALUE);
   if (! integer_all_onesp (size))
     {
       if (! tree_fits_uhwi_p (len))
@@ -2702,7 +2720,7 @@ gimple_fold_builtin_stxcpy_chk (gimple_stmt_iterator *gsi,
   if (! tree_fits_uhwi_p (size))
     return false;
 
-  tree maxlen = get_maxval_strlen (src, 1);
+  tree maxlen = get_maxval_strlen (src, SRK_STRLENMAX);
   if (! integer_all_onesp (size))
     {
       len = c_strlen (src, 1);
@@ -2798,7 +2816,7 @@ gimple_fold_builtin_stxncpy_chk (gimple_stmt_iterator *gsi,
   if (! tree_fits_uhwi_p (size))
     return false;
 
-  tree maxlen = get_maxval_strlen (len, 2);
+  tree maxlen = get_maxval_strlen (len, SRK_INT_VALUE);
   if (! integer_all_onesp (size))
     {
       if (! tree_fits_uhwi_p (len))
@@ -2935,7 +2953,7 @@ gimple_fold_builtin_snprintf_chk (gimple_stmt_iterator *gsi,
 
   if (! integer_all_onesp (size))
     {
-      tree maxlen = get_maxval_strlen (len, 2);
+      tree maxlen = get_maxval_strlen (len, SRK_INT_VALUE);
       if (! tree_fits_uhwi_p (len))
 	{
 	  /* If LEN is not constant, try MAXLEN too.
@@ -3177,7 +3195,7 @@ gimple_fold_builtin_sprintf (gimple_stmt_iterator *gsi)
       tree orig_len = NULL_TREE;
       if (gimple_call_lhs (stmt))
 	{
-	  orig_len = get_maxval_strlen (orig, 0);
+	  orig_len = get_maxval_strlen (orig, SRK_STRLEN);
 	  if (!orig_len)
 	    return false;
 	}
@@ -3310,7 +3328,7 @@ gimple_fold_builtin_snprintf (gimple_stmt_iterator *gsi)
       if (!orig)
 	return false;
 
-      tree orig_len = get_maxval_strlen (orig, 0);
+      tree orig_len = get_maxval_strlen (orig, SRK_STRLEN);
       if (!orig_len || TREE_CODE (orig_len) != INTEGER_CST)
 	return false;
 
diff --git a/gcc/gimple-fold.h b/gcc/gimple-fold.h
index 26e27272249..e1da27625d1 100644
--- a/gcc/gimple-fold.h
+++ b/gcc/gimple-fold.h
@@ -27,7 +27,6 @@ extern tree canonicalize_constructor_val (tree, tree);
 extern tree get_symbol_constant_value (tree);
 extern bool get_range_strlen (tree, tree[2], unsigned = 1,
 			      bool = false, tree * = NULL);
-extern tree get_maxval_strlen (tree, int, tree * = NULL);
 extern void gimplify_and_update_call_from_tree (gimple_stmt_iterator *, tree);
 extern bool fold_stmt (gimple_stmt_iterator *);
 extern bool fold_stmt (gimple_stmt_iterator *, tree (*) (tree));

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]