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]

Fix PR c/41182


This patch fixes PR 41182, a 4.5 regression caused by the constant
expressions changes.  c_fully_fold would return a result wrapped in a
NOP_EXPR where necessary to preserve TREE_NO_WARNING - but if this
result is an operand of a larger expression or will just get wrapped
in a C_MAYBE_CONST_EXPR itself to mark it as fully folded, the
presence of this NOP_EXPR can confuse the folders and cause an ICE
(the folders not only expect all operands of the expression being
folded to be already fully folded themselves, but can ICE if they are
not).  This patch introduces appropriate nop stripping on the results
of c_fully_fold/c_fully_fold_internal where the TREE_NO_WARNING is not
needed.

Bootstrapped with no regressions on x86_64-unknown-linux-gnu.  Applied
to mainline.

2009-10-07  Joseph Myers  <joseph@codesourcery.com>

	PR c/41182
	* c-common.c (c_fully_fold_internal): Strip nops from the result
	of recursive calls to c_fully_fold_internal.
	(c_wrap_maybe_const): New.
	(c_save_expr): Use c_wrap_maybe_const.
	* c-common.h (c_wrap_maybe_const): Declare.
	* c-typeck.c (build_conditional_expr, c_finish_stmt_expr,
	build_binary_op): Use c_wrap_maybe_const.

testsuite:
2009-10-07  Joseph Myers  <joseph@codesourcery.com>

	PR c/41182
	* gcc.c-torture/compile/pr41182-1.c: New.

Index: testsuite/gcc.c-torture/compile/pr41182-1.c
===================================================================
--- testsuite/gcc.c-torture/compile/pr41182-1.c	(revision 0)
+++ testsuite/gcc.c-torture/compile/pr41182-1.c	(revision 0)
@@ -0,0 +1,6 @@
+typedef long unsigned int size_t;
+int _lae_process_opts(char *pr, char *pe)
+{ 
+  return (strlen ("on") < ((size_t) ((pe-&pr[2])>(strlen("on"))                
+                                     ? (pe-&pr[2]) : (strlen("on")))));
+}
Index: c-typeck.c
===================================================================
--- c-typeck.c	(revision 152517)
+++ c-typeck.c	(working copy)
@@ -3940,17 +3940,9 @@ build_conditional_expr (location_t colon
 				     "conditional expression"));
 		    }
 		  if (!op1_maybe_const || TREE_CODE (op1) != INTEGER_CST)
-		    {
-		      op1 = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (op1),
-				    NULL, op1);
-		      C_MAYBE_CONST_EXPR_NON_CONST (op1) = !op1_maybe_const;
-		    }
+		    op1 = c_wrap_maybe_const (op1, !op1_maybe_const);
 		  if (!op2_maybe_const || TREE_CODE (op2) != INTEGER_CST)
-		    {
-		      op2 = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (op2),
-				    NULL, op2);
-		      C_MAYBE_CONST_EXPR_NON_CONST (op2) = !op2_maybe_const;
-		    }
+		    op2 = c_wrap_maybe_const (op2, !op2_maybe_const);
 		}
 	    }
 	}
@@ -8669,8 +8661,7 @@ c_finish_stmt_expr (location_t loc, tree
     {
       /* Even if this looks constant, do not allow it in a constant
 	 expression.  */
-      last = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (last), NULL_TREE, last);
-      C_MAYBE_CONST_EXPR_NON_CONST (last) = 1;
+      last = c_wrap_maybe_const (last, true);
       /* Do not warn if the return value of a statement expression is
 	 unused.  */
       TREE_NO_WARNING (last) = 1;
@@ -9545,17 +9536,9 @@ build_binary_op (location_t location, en
 	      if (!in_late_binary_op)
 		{
 		  if (!op0_maybe_const || TREE_CODE (op0) != INTEGER_CST)
-		    {
-		      op0 = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (op0),
-				    NULL, op0);
-		      C_MAYBE_CONST_EXPR_NON_CONST (op0) = !op0_maybe_const;
-		    }
+		    op0 = c_wrap_maybe_const (op0, !op0_maybe_const);
 		  if (!op1_maybe_const || TREE_CODE (op1) != INTEGER_CST)
-		    {
-		      op1 = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (op1),
-				    NULL, op1);
-		      C_MAYBE_CONST_EXPR_NON_CONST (op1) = !op1_maybe_const;
-		    }
+		    op1 = c_wrap_maybe_const (op1, !op1_maybe_const);
 		}
 	    }
 	}
Index: c-common.c
===================================================================
--- c-common.c	(revision 152517)
+++ c-common.c	(working copy)
@@ -1219,6 +1219,7 @@ c_fully_fold_internal (tree expr, bool i
       op2 = TREE_OPERAND (expr, 2);
       op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
 				   maybe_const_itself);
+      STRIP_TYPE_NOPS (op0);
       if (op0 != orig_op0)
 	ret = build3 (COMPONENT_REF, TREE_TYPE (expr), op0, op1, op2);
       if (ret != expr)
@@ -1235,8 +1236,10 @@ c_fully_fold_internal (tree expr, bool i
       op3 = TREE_OPERAND (expr, 3);
       op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
 				   maybe_const_itself);
+      STRIP_TYPE_NOPS (op0);
       op1 = c_fully_fold_internal (op1, in_init, maybe_const_operands,
 				   maybe_const_itself);
+      STRIP_TYPE_NOPS (op1);
       op1 = decl_constant_value_for_optimization (op1);
       if (op0 != orig_op0 || op1 != orig_op1)
 	ret = build4 (ARRAY_REF, TREE_TYPE (expr), op0, op1, op2, op3);
@@ -1293,6 +1296,7 @@ c_fully_fold_internal (tree expr, bool i
       orig_op1 = op1 = TREE_OPERAND (expr, 1);
       op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
 				   maybe_const_itself);
+      STRIP_TYPE_NOPS (op0);
       if (code != MODIFY_EXPR
 	  && code != PREDECREMENT_EXPR
 	  && code != PREINCREMENT_EXPR
@@ -1304,6 +1308,7 @@ c_fully_fold_internal (tree expr, bool i
       if (code != MODIFY_EXPR)
 	op1 = c_fully_fold_internal (op1, in_init, maybe_const_operands,
 				     maybe_const_itself);
+      STRIP_TYPE_NOPS (op1);
       op1 = decl_constant_value_for_optimization (op1);
       if (op0 != orig_op0 || op1 != orig_op1 || in_init)
 	ret = in_init
@@ -1333,6 +1338,7 @@ c_fully_fold_internal (tree expr, bool i
       orig_op0 = op0 = TREE_OPERAND (expr, 0);
       op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
 				   maybe_const_itself);
+      STRIP_TYPE_NOPS (op0);
       if (code != ADDR_EXPR && code != REALPART_EXPR && code != IMAGPART_EXPR)
 	op0 = decl_constant_value_for_optimization (op0);
       if (op0 != orig_op0 || in_init)
@@ -1372,12 +1378,14 @@ c_fully_fold_internal (tree expr, bool i
       orig_op0 = op0 = TREE_OPERAND (expr, 0);
       orig_op1 = op1 = TREE_OPERAND (expr, 1);
       op0 = c_fully_fold_internal (op0, in_init, &op0_const, &op0_const_self);
+      STRIP_TYPE_NOPS (op0);
 
       unused_p = (op0 == (code == TRUTH_ANDIF_EXPR
 			  ? truthvalue_false_node
 			  : truthvalue_true_node));
       c_inhibit_evaluation_warnings += unused_p;
       op1 = c_fully_fold_internal (op1, in_init, &op1_const, &op1_const_self);
+      STRIP_TYPE_NOPS (op1);
       c_inhibit_evaluation_warnings -= unused_p;
 
       if (op0 != orig_op0 || op1 != orig_op1 || in_init)
@@ -1409,12 +1417,15 @@ c_fully_fold_internal (tree expr, bool i
       orig_op2 = op2 = TREE_OPERAND (expr, 2);
       op0 = c_fully_fold_internal (op0, in_init, &op0_const, &op0_const_self);
 
+      STRIP_TYPE_NOPS (op0);
       c_inhibit_evaluation_warnings += (op0 == truthvalue_false_node);
       op1 = c_fully_fold_internal (op1, in_init, &op1_const, &op1_const_self);
+      STRIP_TYPE_NOPS (op1);
       c_inhibit_evaluation_warnings -= (op0 == truthvalue_false_node);
 
       c_inhibit_evaluation_warnings += (op0 == truthvalue_true_node);
       op2 = c_fully_fold_internal (op2, in_init, &op2_const, &op2_const_self);
+      STRIP_TYPE_NOPS (op2);
       c_inhibit_evaluation_warnings -= (op0 == truthvalue_true_node);
 
       if (op0 != orig_op0 || op1 != orig_op1 || op2 != orig_op2)
@@ -3790,6 +3801,31 @@ pointer_int_sum (location_t loc, enum tr
   return ret;
 }
 
+/* Wrap a C_MAYBE_CONST_EXPR around an expression that is fully folded
+   and if NON_CONST is known not to be permitted in an evaluated part
+   of a constant expression.  */
+
+tree
+c_wrap_maybe_const (tree expr, bool non_const)
+{
+  bool nowarning = TREE_NO_WARNING (expr);
+  location_t loc = EXPR_LOCATION (expr);
+
+  /* This should never be called for C++.  */
+  if (c_dialect_cxx ())
+    gcc_unreachable ();
+
+  /* The result of folding may have a NOP_EXPR to set TREE_NO_WARNING.  */
+  STRIP_TYPE_NOPS (expr);
+  expr = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (expr), NULL, expr);
+  C_MAYBE_CONST_EXPR_NON_CONST (expr) = non_const;
+  if (nowarning)
+    TREE_NO_WARNING (expr) = 1;
+  protected_set_expr_location (expr, loc);
+
+  return expr;
+}
+
 /* Wrap a SAVE_EXPR around EXPR, if appropriate.  Like save_expr, but
    for C folds the inside expression and wraps a C_MAYBE_CONST_EXPR
    around the SAVE_EXPR if needed so that c_fully_fold does not need
@@ -3804,10 +3840,7 @@ c_save_expr (tree expr)
   expr = c_fully_fold (expr, false, &maybe_const);
   expr = save_expr (expr);
   if (!maybe_const)
-    {
-      expr = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (expr), NULL, expr);
-      C_MAYBE_CONST_EXPR_NON_CONST (expr) = 1;
-    }
+    expr = c_wrap_maybe_const (expr, true);
   return expr;
 }
 
Index: c-common.h
===================================================================
--- c-common.h	(revision 152517)
+++ c-common.h	(working copy)
@@ -792,6 +792,7 @@ extern tree c_build_bitfield_integer_typ
 extern bool decl_with_nonnull_addr_p (const_tree);
 extern tree c_fully_fold (tree, bool, bool *);
 extern tree decl_constant_value_for_optimization (tree);
+extern tree c_wrap_maybe_const (tree, bool);
 extern tree c_save_expr (tree);
 extern tree c_common_truthvalue_conversion (location_t, tree);
 extern void c_apply_type_quals_to_decl (int, tree);

-- 
Joseph S. Myers
joseph@codesourcery.com


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