OSDN Git Service

compiler: Prohibit comparisons of funcs, maps, and slices to non-nil.
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-strlen.c
index 71cefaa..a37633a 100644 (file)
@@ -28,6 +28,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-ssa-propagate.h"
 #include "gimple-pretty-print.h"
 #include "params.h"
+#include "expr.h"
 
 /* A vector indexed by SSA_NAME_VERSION.  0 means unknown, positive value
    is an index into strinfo vector, negative value stands for
@@ -176,7 +177,7 @@ get_addr_stridx (tree exp)
 static int
 get_stridx (tree exp)
 {
-  tree l;
+  tree s, o;
 
   if (TREE_CODE (exp) == SSA_NAME)
     return VEC_index (int, ssa_ver_to_stridx, SSA_NAME_VERSION (exp));
@@ -188,14 +189,17 @@ get_stridx (tree exp)
        return idx;
     }
 
-  l = c_strlen (exp, 0);
-  if (l != NULL_TREE
-      && host_integerp (l, 1))
+  s = string_constant (exp, &o);
+  if (s != NULL_TREE
+      && (o == NULL_TREE || host_integerp (o, 0))
+      && TREE_STRING_LENGTH (s) > 0)
     {
-      unsigned HOST_WIDE_INT len = tree_low_cst (l, 1);
-      if (len == (unsigned int) len
-         && (int) len >= 0)
-       return ~(int) len;
+      HOST_WIDE_INT offset = o ? tree_low_cst (o, 0) : 0;
+      const char *p = TREE_STRING_POINTER (s);
+      int max = TREE_STRING_LENGTH (s) - 1;
+
+      if (p[max] == '\0' && offset >= 0 && offset <= max)
+       return ~(int) strlen (p + offset);
     }
   return 0;
 }
@@ -397,7 +401,7 @@ get_string_length (strinfo si)
       callee = gimple_call_fndecl (stmt);
       gcc_assert (callee && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL);
       lhs = gimple_call_lhs (stmt);
-      gcc_assert (implicit_built_in_decls[BUILT_IN_STRCPY] != NULL_TREE);
+      gcc_assert (builtin_decl_implicit_p (BUILT_IN_STPCPY));
       /* unshare_strinfo is intentionally not called here.  The (delayed)
         transformation of strcpy or strcat into stpcpy is done at the place
         of the former strcpy/strcat call and so can affect all the strinfos
@@ -409,7 +413,7 @@ get_string_length (strinfo si)
        case BUILT_IN_STRCAT:
        case BUILT_IN_STRCAT_CHK:
          gsi = gsi_for_stmt (stmt);
-         fn = implicit_built_in_decls[BUILT_IN_STRLEN];
+         fn = builtin_decl_implicit (BUILT_IN_STRLEN);
          gcc_assert (lhs == NULL_TREE);
          lhs_var = create_tmp_var (TREE_TYPE (TREE_TYPE (fn)), NULL);
          add_referenced_var (lhs_var);
@@ -434,9 +438,9 @@ get_string_length (strinfo si)
        case BUILT_IN_STRCPY:
        case BUILT_IN_STRCPY_CHK:
          if (gimple_call_num_args (stmt) == 2)
-           fn = implicit_built_in_decls[BUILT_IN_STPCPY];
+           fn = builtin_decl_implicit (BUILT_IN_STPCPY);
          else
-           fn = built_in_decls[BUILT_IN_STPCPY_CHK];
+           fn = builtin_decl_explicit (BUILT_IN_STPCPY_CHK);
          gcc_assert (lhs == NULL_TREE);
          if (dump_file && (dump_flags & TDF_DETAILS) != 0)
            {
@@ -588,13 +592,13 @@ zero_length_string (tree ptr, strinfo chainsi)
                  || si->prev != chainsi->idx)
                break;
            }
-         gcc_assert (chainsi->length);
+         gcc_assert (chainsi->length || chainsi->stmt);
          if (chainsi->endptr == NULL_TREE)
            {
              chainsi = unshare_strinfo (chainsi);
              chainsi->endptr = ptr;
            }
-         if (integer_zerop (chainsi->length))
+         if (chainsi->length && integer_zerop (chainsi->length))
            {
              if (chainsi->next)
                {
@@ -626,6 +630,8 @@ zero_length_string (tree ptr, strinfo chainsi)
       if (chainsi->first == 0)
        chainsi->first = chainsi->idx;
       chainsi->next = idx;
+      if (chainsi->endptr == NULL_TREE)
+       chainsi->endptr = ptr;
       si->prev = chainsi->idx;
       si->first = chainsi->first;
       si->writable = chainsi->writable;
@@ -654,11 +660,19 @@ adjust_related_strinfos (location_t loc, strinfo origsi, tree adj)
          tree tem;
 
          si = unshare_strinfo (si);
-         gcc_assert (si->length);
-         tem = fold_convert_loc (loc, TREE_TYPE (si->length), adj);
-         si->length = fold_build2_loc (loc, PLUS_EXPR,
-                                       TREE_TYPE (si->length), si->length,
-                                       tem);
+         if (si->length)
+           {
+             tem = fold_convert_loc (loc, TREE_TYPE (si->length), adj);
+             si->length = fold_build2_loc (loc, PLUS_EXPR,
+                                           TREE_TYPE (si->length), si->length,
+                                           tem);
+           }
+         else if (si->stmt != NULL)
+           /* Delayed length computation is unaffected.  */
+           ;
+         else
+           gcc_unreachable ();
+
          si->endptr = NULL_TREE;
          si->dont_invalidate = true;
        }
@@ -692,6 +706,14 @@ find_equal_ptrs (tree ptr, int idx)
        {
        case SSA_NAME:
          break;
+       CASE_CONVERT:
+         if (!POINTER_TYPE_P (TREE_TYPE (ptr)))
+           return;
+         if (TREE_CODE (ptr) == SSA_NAME)
+           break;
+         if (TREE_CODE (ptr) != ADDR_EXPR)
+           return;
+         /* FALLTHRU */
        case ADDR_EXPR:
          {
            int *pidx = addr_stridxptr (TREE_OPERAND (ptr, 0));
@@ -699,10 +721,6 @@ find_equal_ptrs (tree ptr, int idx)
              *pidx = idx;
            return;
          }
-       CASE_CONVERT:
-         if (POINTER_TYPE_P (TREE_TYPE (ptr)))
-           break;
-         return;
        default:
          return;
        }
@@ -1066,8 +1084,7 @@ handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi)
       {
       case BUILT_IN_STRCPY:
       case BUILT_IN_STRCPY_CHK:
-       if (implicit_built_in_decls[BUILT_IN_STPCPY] == NULL_TREE
-           || lhs != NULL_TREE)
+       if (lhs != NULL_TREE || !builtin_decl_implicit_p (BUILT_IN_STPCPY))
          return;
        break;
       case BUILT_IN_STPCPY:
@@ -1114,10 +1131,30 @@ handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi)
 
   if (dsi->length == NULL_TREE)
     {
+      strinfo chainsi;
+
       /* If string length of src is unknown, use delayed length
         computation.  If string lenth of dst will be needed, it
         can be computed by transforming this strcpy call into
         stpcpy and subtracting dst from the return value.  */
+
+      /* Look for earlier strings whose length could be determined if
+        this strcpy is turned into an stpcpy.  */
+
+      if (dsi->prev != 0 && (chainsi = verify_related_strinfos (dsi)) != NULL)
+       {
+         for (; chainsi && chainsi != dsi; chainsi = get_strinfo (chainsi->next))
+           {
+             /* When setting a stmt for delayed length computation
+                prevent all strinfos through dsi from being
+                invalidated.  */
+             chainsi = unshare_strinfo (chainsi);
+             chainsi->stmt = stmt;
+             chainsi->length = NULL_TREE;
+             chainsi->endptr = NULL_TREE;
+             chainsi->dont_invalidate = true;
+           }
+       }
       dsi->stmt = stmt;
       return;
     }
@@ -1150,12 +1187,12 @@ handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi)
   switch (bcode)
     {
     case BUILT_IN_STRCPY:
-      fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
+      fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
       if (lhs)
        VEC_replace (int, ssa_ver_to_stridx, SSA_NAME_VERSION (lhs), didx);
       break;
     case BUILT_IN_STRCPY_CHK:
-      fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
+      fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
       if (lhs)
        VEC_replace (int, ssa_ver_to_stridx, SSA_NAME_VERSION (lhs), didx);
       break;
@@ -1163,7 +1200,7 @@ handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi)
       /* This would need adjustment of the lhs (subtract one),
         or detection that the trailing '\0' doesn't need to be
         written, if it will be immediately overwritten.
-      fn = built_in_decls[BUILT_IN_MEMPCPY];  */
+      fn = builtin_decl_explicit (BUILT_IN_MEMPCPY);  */
       if (lhs)
        {
          dsi->endptr = lhs;
@@ -1174,7 +1211,7 @@ handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi)
       /* This would need adjustment of the lhs (subtract one),
         or detection that the trailing '\0' doesn't need to be
         written, if it will be immediately overwritten.
-      fn = built_in_decls[BUILT_IN_MEMPCPY_CHK];  */
+      fn = builtin_decl_explicit (BUILT_IN_MEMPCPY_CHK);  */
       if (lhs)
        {
          dsi->endptr = lhs;
@@ -1297,7 +1334,7 @@ handle_builtin_memcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi)
   if (si != NULL)
     newlen = si->length;
   else
-    newlen = build_int_cst (TREE_TYPE (len), ~idx);
+    newlen = build_int_cst (size_type_node, ~idx);
   oldlen = NULL_TREE;
   if (olddsi != NULL)
     {
@@ -1396,8 +1433,7 @@ handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi)
         with length endptr - p if we need to compute the length
         later on.  Don't do this transformation if we don't need
         it.  */
-      if (implicit_built_in_decls[BUILT_IN_STPCPY] != NULL_TREE
-         && lhs == NULL_TREE)
+      if (builtin_decl_implicit_p (BUILT_IN_STPCPY) && lhs == NULL_TREE)
        {
          if (didx == 0)
            {
@@ -1456,8 +1492,7 @@ handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi)
   else
     {
       dsi->length = NULL;
-      if (implicit_built_in_decls[BUILT_IN_STPCPY] != NULL_TREE
-         && lhs == NULL_TREE)
+      if (lhs == NULL_TREE && builtin_decl_implicit_p (BUILT_IN_STPCPY))
        dsi->dont_invalidate = true;
     }
 
@@ -1477,15 +1512,15 @@ handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi)
     {
     case BUILT_IN_STRCAT:
       if (srclen != NULL_TREE)
-       fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
+       fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
       else
-       fn = implicit_built_in_decls[BUILT_IN_STRCPY];
+       fn = builtin_decl_implicit (BUILT_IN_STRCPY);
       break;
     case BUILT_IN_STRCAT_CHK:
       if (srclen != NULL_TREE)
-       fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
+       fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
       else
-       fn = built_in_decls[BUILT_IN_STRCPY_CHK];
+       fn = builtin_decl_explicit (BUILT_IN_STRCPY_CHK);
       objsz = gimple_call_arg (stmt, 2);
       break;
     default: