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"))))); +}