diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index d381c7023122ab4bfc5c92e2aa2b71046fb6146e..885532b2fd8f2a21aed926276897391eb7e09873 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,14 @@
+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.
+
 2009-10-07  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
 
 	* real.c: Fix comment to reflect actual exponent size.
diff --git a/gcc/c-common.c b/gcc/c-common.c
index bf57cb8a2df08be88154521a34a5f4e21f26bc6d..fb2a84ebbf4666fb0ecdb52eb0984ecb8d658d94 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -1219,6 +1219,7 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
       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 in_init, bool *maybe_const_operands,
       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 in_init, bool *maybe_const_operands,
       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 in_init, bool *maybe_const_operands,
       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 in_init, bool *maybe_const_operands,
       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 in_init, bool *maybe_const_operands,
       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 in_init, bool *maybe_const_operands,
       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 tree_code resultcode,
   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;
 }
 
diff --git a/gcc/c-common.h b/gcc/c-common.h
index db4f910e81b6c4f7a03ad0866b992cad4ea5b1cb..61d52c870fb0ea118719f9432917d1f6a54c7f6c 100644
--- a/gcc/c-common.h
+++ b/gcc/c-common.h
@@ -792,6 +792,7 @@ extern tree c_build_bitfield_integer_type (unsigned HOST_WIDE_INT, int);
 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);
diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c
index 4c55e587de3c9a5c82943ba52e5fda60325a4a57..e7425a77d65e42727dbd4c303806bc77379a9129 100644
--- a/gcc/c-typeck.c
+++ b/gcc/c-typeck.c
@@ -3940,17 +3940,9 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
 				     "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 body)
     {
       /* 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, enum tree_code code,
 	      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);
 		}
 	    }
 	}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index fe14298215ebbc6fa872c24ddb19f15e57633809..9b9b141b9f3066e8f03e3f25dbb43bb90627fc33 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2009-10-07  Joseph Myers  <joseph@codesourcery.com>
+
+	PR c/41182
+	* gcc.c-torture/compile/pr41182-1.c: New.
+
 2009-10-07  Jason Merrill  <jason@redhat.com>
 
 	* g++.dg/cpp0x/variadic95.C: New.
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr41182-1.c b/gcc/testsuite/gcc.c-torture/compile/pr41182-1.c
new file mode 100644
index 0000000000000000000000000000000000000000..017174938b3bf0a8ebbafd4cb680c83e6ec258b7
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr41182-1.c
@@ -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")))));
+}