tree-ssa-ccp.c (ccp_fold_stmt): Fold calls and propagate into call arguments.
authorRichard Guenther <rguenther@suse.de>
Thu, 28 Jan 2010 14:42:17 +0000 (14:42 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Thu, 28 Jan 2010 14:42:17 +0000 (14:42 +0000)
2010-01-28  Richard Guenther  <rguenther@suse.de>

* tree-ssa-ccp.c (ccp_fold_stmt): Fold calls and propagate
into call arguments.

* gcc.dg/Wobjsize-1.h: New testcase.
* gcc.dg/Wobjsize-1.c: Likewise.

From-SVN: r156323

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/Wobjsize-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/Wobjsize-1.h [new file with mode: 0644]
gcc/tree-ssa-ccp.c

index a96de7e2b7655e6063ffbd614da033f50f923f54..23cc57783205d83e88bac172fa25a53002d569bc 100644 (file)
@@ -1,3 +1,8 @@
+2010-01-28  Richard Guenther  <rguenther@suse.de>
+
+       * tree-ssa-ccp.c (ccp_fold_stmt): Fold calls and propagate
+       into call arguments.
+
 2010-01-28  Richard Guenther  <rguenther@suse.de>
 
        PR middle-end/42883
index 7706f8702a252f6be12140300b23ef59e38613bc..a1c2ba3aff89e973b2154f5993872dd055b7ff70 100644 (file)
@@ -1,3 +1,8 @@
+2010-01-28  Richard Guenther  <rguenther@suse.de>
+
+       * gcc.dg/Wobjsize-1.h: New testcase.
+       * gcc.dg/Wobjsize-1.c: Likewise.
+
 2010-01-28  Richard Guenther  <rguenther@suse.de>
 
        PR middle-end/42883
diff --git a/gcc/testsuite/gcc.dg/Wobjsize-1.c b/gcc/testsuite/gcc.dg/Wobjsize-1.c
new file mode 100644 (file)
index 0000000..17e554b
--- /dev/null
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wall" } */
+
+#include "Wobjsize-1.h"
+
+char buf[6];
+int main(int argc, char **argv)
+{
+  strcpy (buf,"hello ");
+  return 0;
+}
+
+/* { dg-warning "will always overflow destination buffer" "" { target *-*-* } 6 } */
+/* { dg-message "file included" "" { target *-*-* } 0 } */
+/* { dg-message "inlined from" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.dg/Wobjsize-1.h b/gcc/testsuite/gcc.dg/Wobjsize-1.h
new file mode 100644 (file)
index 0000000..a879f6d
--- /dev/null
@@ -0,0 +1,8 @@
+#pragma GCC system_header
+
+extern __inline __attribute__ ((__always_inline__,__artificial__,__gnu_inline__)) char *
+__attribute__ ((__nothrow__)) strcpy (char *__restrict __dest, __const char *__restrict __src)
+{
+  return __builtin___strcpy_chk (__dest, __src, __builtin_object_size (__dest, 2 > 1));
+}
+
index b40dba36d081d206a1985bd4a96d2c32918092ac..f6380ebdbe7bcc905e930a5574b494b18d630502 100644 (file)
@@ -1480,25 +1480,79 @@ static bool
 ccp_fold_stmt (gimple_stmt_iterator *gsi)
 {
   gimple stmt = gsi_stmt (*gsi);
-  prop_value_t val;
 
-  if (gimple_code (stmt) != GIMPLE_COND)
-    return false;
+  switch (gimple_code (stmt))
+    {
+    case GIMPLE_COND:
+      {
+       prop_value_t val;
+       /* Statement evaluation will handle type mismatches in constants
+          more gracefully than the final propagation.  This allows us to
+          fold more conditionals here.  */
+       val = evaluate_stmt (stmt);
+       if (val.lattice_val != CONSTANT
+           || TREE_CODE (val.value) != INTEGER_CST)
+         return false;
+
+       if (integer_zerop (val.value))
+         gimple_cond_make_false (stmt);
+       else
+         gimple_cond_make_true (stmt);
 
-  /* Statement evaluation will handle type mismatches in constants
-     more gracefully than the final propagation.  This allows us to
-     fold more conditionals here.  */
-  val = evaluate_stmt (stmt);
-  if (val.lattice_val != CONSTANT
-      || TREE_CODE (val.value) != INTEGER_CST)
-    return false;
+       return true;
+      }
 
-  if (integer_zerop (val.value))
-    gimple_cond_make_false (stmt);
-  else
-    gimple_cond_make_true (stmt);
+    case GIMPLE_CALL:
+      {
+       tree lhs = gimple_call_lhs (stmt);
+       prop_value_t *val;
+       tree argt;
+       bool changed = false;
+       unsigned i;
+
+       /* If the call was folded into a constant make sure it goes
+          away even if we cannot propagate into all uses because of
+          type issues.  */
+       if (lhs
+           && TREE_CODE (lhs) == SSA_NAME
+           && (val = get_value (lhs))
+           && val->lattice_val == CONSTANT)
+         {
+           tree new_rhs = val->value;
+           if (!useless_type_conversion_p (TREE_TYPE (lhs),
+                                           TREE_TYPE (new_rhs)))
+             new_rhs = fold_convert (TREE_TYPE (lhs), new_rhs);
+           update_call_from_tree (gsi, new_rhs);
+           return true;
+         }
 
-  return true;
+       /* Propagate into the call arguments.  Compared to replace_uses_in
+          this can use the argument slot types for type verification
+          instead of the current argument type.  We also can safely
+          drop qualifiers here as we are dealing with constants anyway.  */
+       argt = TYPE_ARG_TYPES (TREE_TYPE (TREE_TYPE (gimple_call_fn (stmt))));
+       for (i = 0; i < gimple_call_num_args (stmt) && argt;
+            ++i, argt = TREE_CHAIN (argt))
+         {
+           tree arg = gimple_call_arg (stmt, i);
+           if (TREE_CODE (arg) == SSA_NAME
+               && (val = get_value (arg))
+               && val->lattice_val == CONSTANT
+               && useless_type_conversion_p
+                    (TYPE_MAIN_VARIANT (TREE_VALUE (argt)),
+                     TYPE_MAIN_VARIANT (TREE_TYPE (val->value))))
+             {
+               gimple_call_set_arg (stmt, i, val->value);
+               changed = true;
+             }
+         }
+
+       return changed;
+      }
+
+    default:
+      return false;
+    }
 }
 
 /* Visit the assignment statement STMT.  Set the value of its LHS to the