PATCH RFC: Add -Wstrict-overflow to tree-vrp.c

Ian Lance Taylor iant@google.com
Mon Mar 5 18:23:00 GMT 2007


This patch adds support for -Wstrict-overflow to tree-vrp.c.  This is
the last in the signed overflow series.

I plan to commit this patch in a few days if there are no objections.

Bootstrapped and tested on i686-pc-linux-gnu.

Ian


gcc/ChangeLog:
2007-03-05  Ian Lance Taylor  <iant@google.com>

	* tree-vrp.c: Include "intl.h".
	(usable_range_p): New static function.
	(compare_values_warnv): Don't test TYPE_OVERFLOW_UNDEFINED for
	overflowed values, juts set *strict_overflow_p.
	(compare_values): Only return -2 if one of the operands is not a
	constant.
	(compare_ranges): Call usable_range_p.
	(compare_range_with_value): Likewise.
	(vrp_evaluate_conditional_warnv): Rename from
	vrp_evaluate_conditional.  Make static.  Change all callers.
	(vrp_evaluate_conditional): New function.
	(simplify_div_or_mod_using_ranges): Issue warning about reliance
	on signed overflow.
	(simplify_abs_using_ranges): Likewise.
	(simplify_stmt_for_jump_threading): Add within_stmt parameter.
	* tree-ssa-dom.c (simplify_stmt_for_jump_threading): Add
	within_stmt parameter.
	* tree-ssa-propagate.c (fold_predicate_in): Update call to
	vrp_evaluate_conditional.
	* tree-ssa-threadedge.c
	(record_temporary_equivalences_from_stmts_at_dest): Change
	simplify parameter to take a second tree parameter.
	(simplify_control_stmt_condition): Likewise.
	(thread_across_edge): Likewise.
	* tree-flow.h (vrp_evaluate_conditional): Update declaration.
	(thread_across_edge): Likewise.
	* gcc/Makefile.in (tree-vrp.o): Depend upon intl.h.

gcc/testsuite/ChangeLog:
2007-03-05  Ian Lance Taylor  <iant@google.com>

	* gcc.dg/no-strict-overflow-5.c: New test.
	* gcc.dg/no-strict-overflow-6.c: New test.
	* gcc.dg/Wstrict-overflow-11.c: New test.
	* gcc.dg/Wstrict-overflow-12.c: New test.
	* gcc.dg/Wstrict-overflow-13.c: New test.
	* gcc.dg/Wstrict-overflow-14.c: New test.
	* gcc.dg/Wstrict-overflow-15.c: New test.


Index: gcc/tree-vrp.c
===================================================================
--- gcc/tree-vrp.c	(revision 122487)
+++ gcc/tree-vrp.c	(working copy)
@@ -33,6 +33,7 @@ Boston, MA 02110-1301, USA.  */
 #include "timevar.h"
 #include "diagnostic.h"
 #include "toplev.h"
+#include "intl.h"
 #include "cfgloop.h"
 #include "tree-scalar-evolution.h"
 #include "tree-ssa-propagate.h"
@@ -46,6 +47,7 @@ static sbitmap found_in_subgraph;
 static int compare_values (tree val1, tree val2);
 static int compare_values_warnv (tree val1, tree val2, bool *);
 static void vrp_meet (value_range_t *, value_range_t *);
+static tree vrp_evaluate_conditional_warnv (tree, bool, bool *);
 
 /* Location information for ASSERT_EXPRs.  Each instance of this
    structure describes an ASSERT_EXPR for an SSA name.  Since a single
@@ -543,6 +545,32 @@ overflow_infinity_range_p (value_range_t
 	      || is_overflow_infinity (vr->max)));
 }
 
+/* Return false if we can not make a valid comparison based on VR;
+   this will be the case if it uses an overflow infinity and overflow
+   is not undefined (i.e., -fno-strict-overflow is in effect).
+   Otherwise return true, and set *STRICT_OVERFLOW_P to true if VR
+   uses an overflow infinity.  */
+
+static bool
+usable_range_p (value_range_t *vr, bool *strict_overflow_p)
+{
+  gcc_assert (vr->type == VR_RANGE);
+  if (is_overflow_infinity (vr->min))
+    {
+      *strict_overflow_p = true;
+      if (!TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (vr->min)))
+	return false;
+    }
+  if (is_overflow_infinity (vr->max))
+    {
+      *strict_overflow_p = true;
+      if (!TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (vr->max)))
+	return false;
+    }
+  return true;
+}
+
+
 /* Like tree_expr_nonnegative_warnv_p, but this function uses value
    ranges obtained so far.  */
 
@@ -783,9 +811,8 @@ compare_values_warnv (tree val1, tree va
 	 infinities.  */
       if (TREE_OVERFLOW (val1) || TREE_OVERFLOW (val2))
 	{
-	  if (!TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (val1)))
-	    return -2;
-
+	  if (strict_overflow_p != NULL)
+	    *strict_overflow_p = true;
 	  if (is_negative_overflow_infinity (val1))
 	    return is_negative_overflow_infinity (val2) ? 0 : -1;
 	  else if (is_negative_overflow_infinity (val2))
@@ -831,8 +858,8 @@ compare_values_warnv (tree val1, tree va
     }
 }
 
-/* Compare values like compare_values_warnv, but treat comparisons
-   which rely on undefined overflow as incomparable.  */
+/* Compare values like compare_values_warnv, but treat comparisons of
+   nonconstants which rely on undefined overflow as incomparable.  */
 
 static int
 compare_values (tree val1, tree val2)
@@ -842,7 +869,8 @@ compare_values (tree val1, tree val2)
 
   sop = false;
   ret = compare_values_warnv (val1, val2, &sop);
-  if (sop)
+  if (sop
+      && (!is_gimple_min_invariant (val1) || !is_gimple_min_invariant (val2)))
     ret = -2;
   return ret;
 }
@@ -2357,7 +2385,7 @@ static void
 extract_range_from_comparison (value_range_t *vr, tree expr)
 {
   bool sop = false;
-  tree val = vrp_evaluate_conditional (expr, false, &sop);
+  tree val = vrp_evaluate_conditional_warnv (expr, false, &sop);
 
   /* A disadvantage of using a special infinity as an overflow
      representation is that we lose the ability to record overflow
@@ -2602,6 +2630,10 @@ compare_ranges (enum tree_code comp, val
       return NULL_TREE;
     }
 
+  if (!usable_range_p (vr0, strict_overflow_p)
+      || !usable_range_p (vr1, strict_overflow_p))
+    return NULL_TREE;
+
   /* Simplify processing.  If COMP is GT_EXPR or GE_EXPR, switch the
      operands around and change the comparison code.  */
   if (comp == GT_EXPR || comp == GE_EXPR)
@@ -2735,6 +2767,9 @@ compare_range_with_value (enum tree_code
       return NULL_TREE;
     }
 
+  if (!usable_range_p (vr, strict_overflow_p))
+    return NULL_TREE;
+
   if (comp == EQ_EXPR)
     {
       /* EQ_EXPR may only be computed if VR represents exactly
@@ -4529,8 +4564,9 @@ compare_names (enum tree_code comp, tree
    Set *STRICT_OVERFLOW_P to indicate whether we relied on an overflow
    infinity to produce the result.  */
 
-tree
-vrp_evaluate_conditional (tree cond, bool use_equiv_p, bool *strict_overflow_p)
+static tree
+vrp_evaluate_conditional_warnv (tree cond, bool use_equiv_p,
+				bool *strict_overflow_p)
 {
   gcc_assert (TREE_CODE (cond) == SSA_NAME
               || TREE_CODE_CLASS (TREE_CODE (cond)) == tcc_comparison);
@@ -4607,6 +4643,55 @@ vrp_evaluate_conditional (tree cond, boo
   return NULL_TREE;
 }
 
+/* Given COND within STMT, try to simplify it based on value range
+   information.  Return NULL if the conditional can not be evaluated.
+   The ranges of all the names equivalent with the operands in COND
+   will be used when trying to compute the value.  If the result is
+   based on undefined signed overflow, issue a warning if
+   appropriate.  */
+
+tree
+vrp_evaluate_conditional (tree cond, tree stmt)
+{
+  bool sop;
+  tree ret;
+
+  sop = false;
+  ret = vrp_evaluate_conditional_warnv (cond, true, &sop);
+
+  if (ret && sop)
+    {
+      enum warn_strict_overflow_code wc;
+      const char* warnmsg;
+
+      if (is_gimple_min_invariant (ret))
+	{
+	  wc = WARN_STRICT_OVERFLOW_CONDITIONAL;
+	  warnmsg = G_("assuming signed overflow does not occur when "
+		       "simplifying conditional to constant");
+	}
+      else
+	{
+	  wc = WARN_STRICT_OVERFLOW_COMPARISON;
+	  warnmsg = G_("assuming signed overflow does not occur when "
+		       "simplifying conditional");
+	}
+
+      if (issue_strict_overflow_warning (wc))
+	{
+	  location_t locus;
+
+	  if (!EXPR_HAS_LOCATION (stmt))
+	    locus = input_location;
+	  else
+	    locus = EXPR_LOCATION (stmt);
+	  warning (OPT_Wstrict_overflow, "%H%s", &locus, warnmsg);
+	}
+    }
+
+  return ret;
+}
+
 
 /* Visit conditional statement STMT.  If we can determine which edge
    will be taken out of STMT's basic block, record it in
@@ -4691,7 +4776,7 @@ vrp_visit_cond_stmt (tree stmt, edge *ta
      MICO, TRAMP3D and SPEC2000) showed that doing this results in
      4 more predicates folded in SPEC.  */
   sop = false;
-  val = vrp_evaluate_conditional (cond, false, &sop);
+  val = vrp_evaluate_conditional_warnv (cond, false, &sop);
   if (val)
     {
       if (!sop)
@@ -5069,6 +5154,23 @@ simplify_div_or_mod_using_ranges (tree s
       bool sop = false;
 
       val = compare_range_with_value (GT_EXPR, vr, integer_zero_node, &sop);
+
+      if (val
+	  && sop
+	  && integer_onep (val)
+	  && issue_strict_overflow_warning (WARN_STRICT_OVERFLOW_MISC))
+	{
+	  location_t locus;
+
+	  if (!EXPR_HAS_LOCATION (stmt))
+	    locus = input_location;
+	  else
+	    locus = EXPR_LOCATION (stmt);
+	  warning (OPT_Wstrict_overflow,
+		   ("%Hassuming signed overflow does not occur when "
+		    "simplifying / or %% to >> or &"),
+		   &locus);
+	}
     }
 
   if (val && integer_onep (val))
@@ -5136,6 +5238,20 @@ simplify_abs_using_ranges (tree stmt, tr
 	{
 	  tree t;
 
+	  if (sop && issue_strict_overflow_warning (WARN_STRICT_OVERFLOW_MISC))
+	    {
+	      location_t locus;
+
+	      if (!EXPR_HAS_LOCATION (stmt))
+		locus = input_location;
+	      else
+		locus = EXPR_LOCATION (stmt);
+	      warning (OPT_Wstrict_overflow,
+		       ("%Hassuming signed overflow does not occur when "
+			"simplifying abs (X) to X or -X"),
+		       &locus);
+	    }
+
 	  if (integer_onep (val))
 	    t = build1 (NEGATE_EXPR, TREE_TYPE (op), op);
 	  else
@@ -5328,21 +5444,21 @@ simplify_stmt_using_ranges (tree stmt)
    restored.  */
 static VEC(tree,heap) *stack;
 
-/* A trivial wrapper so that we can present the generic jump
-   threading code with a simple API for simplifying statements.  */
+/* A trivial wrapper so that we can present the generic jump threading
+   code with a simple API for simplifying statements.  STMT is the
+   statement we want to simplify, WITHIN_STMT provides the location
+   for any overflow warnings.  */
+
 static tree
-simplify_stmt_for_jump_threading (tree stmt)
+simplify_stmt_for_jump_threading (tree stmt, tree within_stmt)
 {
-  bool sop;
-
   /* We only use VRP information to simplify conditionals.  This is
      overly conservative, but it's unclear if doing more would be
      worth the compile time cost.  */
   if (TREE_CODE (stmt) != COND_EXPR)
     return NULL;
 
-  sop = false;
-  return vrp_evaluate_conditional (COND_EXPR_COND (stmt), true, &sop);
+  return vrp_evaluate_conditional (COND_EXPR_COND (stmt), within_stmt);
 }
 
 /* Blocks which have more than one predecessor and more than
Index: gcc/testsuite/gcc.dg/Wstrict-overflow-12.c
===================================================================
--- gcc/testsuite/gcc.dg/Wstrict-overflow-12.c	(revision 0)
+++ gcc/testsuite/gcc.dg/Wstrict-overflow-12.c	(revision 0)
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-fstrict-overflow -O2 -Wstrict-overflow=2" } */
+
+/* Source: Ian Lance Taylor.  Dual of no-strict-overflow-6.c.  */
+
+/* VRP test.  This turns into an infinite loop when using strict
+   overflow semantics.  */
+
+int
+foo ()
+{
+  int i, bits;
+  for (i = 1, bits = 1; i > 0; i += i) /* { dg-warning "assuming signed overflow does not occur" "correct warning" } */
+    ++bits;
+  return bits;
+}
Index: gcc/testsuite/gcc.dg/Wstrict-overflow-14.c
===================================================================
--- gcc/testsuite/gcc.dg/Wstrict-overflow-14.c	(revision 0)
+++ gcc/testsuite/gcc.dg/Wstrict-overflow-14.c	(revision 0)
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-fstrict-overflow -O2 -Wstrict-overflow=4" } */
+
+/* Source: Ian Lance Taylor.  */
+
+int
+foo (int j)
+{
+  int i;
+  int sum = 0;
+
+  for (i = 1; i < j; i += i)
+    sum += i / 16; /* { dg-warning "assuming signed overflow does not occur" "" } */
+  return sum;
+}
Index: gcc/testsuite/gcc.dg/no-strict-overflow-5.c
===================================================================
--- gcc/testsuite/gcc.dg/no-strict-overflow-5.c	(revision 0)
+++ gcc/testsuite/gcc.dg/no-strict-overflow-5.c	(revision 0)
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-fno-strict-overflow -O2 -fdump-tree-final_cleanup" } */
+
+/* Dual of strict-overflow-5.c.  */
+
+/* We can only unroll when using strict overflow semantics.  */
+
+int foo (int i)
+{
+  int index;
+  int r=0;
+ 
+  for (index = i; index <= i+4; index+=2) 
+    r++;
+ 
+  return r;
+}
+
+/* { dg-final { scan-tree-dump-times "r = 3" 0 "final_cleanup" } } */
+/* { dg-final { cleanup-tree-dump "final_cleanup" } } */
Index: gcc/testsuite/gcc.dg/Wstrict-overflow-11.c
===================================================================
--- gcc/testsuite/gcc.dg/Wstrict-overflow-11.c	(revision 0)
+++ gcc/testsuite/gcc.dg/Wstrict-overflow-11.c	(revision 0)
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-fstrict-overflow -O2 -Wstrict-overflow=1" } */
+
+/* Based on strict-overflow-5.c.  */
+
+/* We can only unroll when using strict overflow semantics.  */
+
+int foo (int i)
+{
+  int index;
+  int r=0;
+ 
+  for (index = i; index <= i+4; index+=2) /* { dg-warning "assuming signed overflow does not occur" "correct warning" } */
+    r++;
+ 
+  return r;
+}
Index: gcc/testsuite/gcc.dg/Wstrict-overflow-13.c
===================================================================
--- gcc/testsuite/gcc.dg/Wstrict-overflow-13.c	(revision 0)
+++ gcc/testsuite/gcc.dg/Wstrict-overflow-13.c	(revision 0)
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-fstrict-overflow -O2 -Wstrict-overflow=2" } */
+
+/* Source: Ian Lance Taylor.  Dual of no-strict-overflow-6.c.  */
+
+/* VRP test.  This turns into an infinite loop (depending on what
+   bigtime_test does), but at least we warn about it.  */
+
+extern int bigtime_test (int);
+int
+foo ()
+{
+  int j;
+  for (j = 1; 0 < j; j *= 2) /* { dg-warning "assuming signed overflow does not occur" "correct warning" } */
+    if (! bigtime_test (j))
+      return 1;
+  return 0;
+}
Index: gcc/testsuite/gcc.dg/Wstrict-overflow-15.c
===================================================================
--- gcc/testsuite/gcc.dg/Wstrict-overflow-15.c	(revision 0)
+++ gcc/testsuite/gcc.dg/Wstrict-overflow-15.c	(revision 0)
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-fstrict-overflow -O2 -Wstrict-overflow=4" } */
+
+/* Source: Ian Lance Taylor.  */
+
+int
+foo (int j)
+{
+  int i;
+  int sum = 0;
+
+  for (i = 1; i < j; i += i)
+    sum += __builtin_abs (i); /* { dg-warning "assuming signed overflow does not occur" "" } */
+  return sum;
+}
Index: gcc/testsuite/gcc.dg/no-strict-overflow-6.c
===================================================================
--- gcc/testsuite/gcc.dg/no-strict-overflow-6.c	(revision 0)
+++ gcc/testsuite/gcc.dg/no-strict-overflow-6.c	(revision 0)
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-fno-strict-overflow -O2 -fdump-tree-final_cleanup" } */
+
+/* Source: Ian Lance Taylor.  */
+
+/* VRP test.  We can not simplify the conditional when no using strict
+   overflow semantics.  We don't test this with -fstrict-overflow
+   because it turns into an infinite loop.  That is OK but it would
+   also be OK to not do that.  */
+
+int
+foo ()
+{
+  int i, bits;
+  for (i = 1, bits = 1; i > 0; i += i)
+    ++bits;
+  return bits;
+}
+
+/* { dg-final { scan-tree-dump "return bits" "final_cleanup" } } */
+/* { dg-final { cleanup-tree-dump "final_cleanup" } } */
Index: gcc/tree-ssa-dom.c
===================================================================
--- gcc/tree-ssa-dom.c	(revision 122487)
+++ gcc/tree-ssa-dom.c	(working copy)
@@ -554,7 +554,7 @@ restore_vars_to_original_value (void)
 /* A trivial wrapper so that we can present the generic jump
    threading code with a simple API for simplifying statements.  */
 static tree
-simplify_stmt_for_jump_threading (tree stmt)
+simplify_stmt_for_jump_threading (tree stmt, tree within_stmt ATTRIBUTE_UNUSED)
 {
   return lookup_avail_expr (stmt, false);
 }
Index: gcc/tree-ssa-propagate.c
===================================================================
--- gcc/tree-ssa-propagate.c	(revision 122487)
+++ gcc/tree-ssa-propagate.c	(working copy)
@@ -1100,7 +1100,6 @@ fold_predicate_in (tree stmt)
   tree *pred_p = NULL;
   bool modify_stmt_p = false;
   tree val;
-  bool sop;
 
   if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT
       && COMPARISON_CLASS_P (GIMPLE_STMT_OPERAND (stmt, 1)))
@@ -1113,8 +1112,7 @@ fold_predicate_in (tree stmt)
   else
     return false;
 
-  sop = false;
-  val = vrp_evaluate_conditional (*pred_p, true, &sop);
+  val = vrp_evaluate_conditional (*pred_p, stmt);
   if (val)
     {
       if (modify_stmt_p)
Index: gcc/tree-flow.h
===================================================================
--- gcc/tree-flow.h	(revision 122487)
+++ gcc/tree-flow.h	(working copy)
@@ -776,7 +776,7 @@ bool fold_stmt_inplace (tree);
 tree widen_bitfield (tree, tree, tree);
 
 /* In tree-vrp.c  */
-tree vrp_evaluate_conditional (tree, bool, bool *);
+tree vrp_evaluate_conditional (tree, tree);
 void simplify_stmt_using_ranges (tree);
 
 /* In tree-ssa-dom.c  */
@@ -910,7 +910,7 @@ bool contains_abnormal_ssa_name_p (tree)
 /* In tree-ssa-threadedge.c */
 extern bool potentially_threadable_block (basic_block);
 extern void thread_across_edge (tree, edge, bool,
-				VEC(tree, heap) **, tree (*) (tree));
+				VEC(tree, heap) **, tree (*) (tree, tree));
 
 /* In tree-ssa-loop-im.c  */
 /* The possibilities of statement movement.  */
Index: gcc/Makefile.in
===================================================================
--- gcc/Makefile.in	(revision 122487)
+++ gcc/Makefile.in	(working copy)
@@ -2052,7 +2052,7 @@ tree-vn.o : tree-vn.c $(CONFIG_H) $(SYST
 tree-vrp.o : tree-vrp.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
    $(TREE_FLOW_H) tree-pass.h $(TREE_DUMP_H) $(DIAGNOSTIC_H) $(GGC_H) \
    $(BASIC_BLOCK_H) tree-ssa-propagate.h $(FLAGS_H) $(TREE_DUMP_H) \
-   $(CFGLOOP_H) $(SCEV_H) tree-chrec.h $(TIMEVAR_H) toplev.h
+   $(CFGLOOP_H) $(SCEV_H) tree-chrec.h $(TIMEVAR_H) toplev.h intl.h
 tree-cfg.o : tree-cfg.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
    $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(GGC_H) $(FLAGS_H) output.h \
    $(DIAGNOSTIC_H) $(FUNCTION_H) $(TIMEVAR_H) $(TM_H) coretypes.h \
Index: gcc/tree-ssa-threadedge.c
===================================================================
--- gcc/tree-ssa-threadedge.c	(revision 122487)
+++ gcc/tree-ssa-threadedge.c	(working copy)
@@ -211,7 +211,8 @@ record_temporary_equivalences_from_phis 
 static tree
 record_temporary_equivalences_from_stmts_at_dest (edge e,
 						  VEC(tree, heap) **stack,
-						  tree (*simplify) (tree))
+						  tree (*simplify) (tree,
+								    tree))
 {
   block_stmt_iterator bsi;
   tree stmt = NULL;
@@ -315,7 +316,7 @@ record_temporary_equivalences_from_stmts
 	      cached_lhs = fold (pre_fold_expr);
 	      if (TREE_CODE (cached_lhs) != SSA_NAME
 		  && !is_gimple_min_invariant (cached_lhs))
-	        cached_lhs = (*simplify) (stmt);
+	        cached_lhs = (*simplify) (stmt, stmt);
 	    }
 
 	  /* Restore the statement's original uses/defs.  */
@@ -353,7 +354,7 @@ static tree
 simplify_control_stmt_condition (edge e,
 				 tree stmt,
 				 tree dummy_cond,
-				 tree (*simplify) (tree),
+				 tree (*simplify) (tree, tree),
 				 bool handle_dominating_asserts)
 {
   tree cond, cached_lhs;
@@ -439,7 +440,7 @@ simplify_control_stmt_condition (edge e,
       /* If we have not simplified the condition down to an invariant,
 	 then use the pass specific callback to simplify the condition.  */
       if (! is_gimple_min_invariant (cached_lhs))
-	cached_lhs = (*simplify) (dummy_cond);
+	cached_lhs = (*simplify) (dummy_cond, stmt);
     }
 
   /* We can have conditionals which just test the state of a variable
@@ -466,7 +467,7 @@ simplify_control_stmt_condition (edge e,
       /* If we haven't simplified to an invariant yet, then use the
 	 pass specific callback to try and simplify it further.  */
       if (cached_lhs && ! is_gimple_min_invariant (cached_lhs))
-        cached_lhs = (*simplify) (stmt);
+        cached_lhs = (*simplify) (stmt, stmt);
     }
   else
     cached_lhs = NULL;
@@ -494,7 +495,7 @@ thread_across_edge (tree dummy_cond,
 		    edge e,
 		    bool handle_dominating_asserts,
 		    VEC(tree, heap) **stack,
-		    tree (*simplify) (tree))
+		    tree (*simplify) (tree, tree))
 {
   tree stmt;
 



More information about the Gcc-patches mailing list