gimple-fold.c (strlen_range_kind): New enum.
authorMartin Sebor <msebor@redhat.com>
Mon, 31 Dec 2018 01:01:10 +0000 (01:01 +0000)
committerJeff Law <law@gcc.gnu.org>
Mon, 31 Dec 2018 01:01:10 +0000 (18:01 -0700)
* 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.

Co-Authored-By: Jeff Law <law@redhat.com>
From-SVN: r267482

gcc/ChangeLog
gcc/gimple-fold.c
gcc/gimple-fold.h

index bb02095..1ee865e 100644 (file)
@@ -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
index 4f84f0c..76fa328 100644 (file)
@@ -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;
 
index 26e2727..e1da276 100644 (file)
@@ -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));