diff options
author | Joseph Myers <joseph@codesourcery.com> | 2009-10-08 01:32:51 +0100 |
---|---|---|
committer | Joseph Myers <jsm28@gcc.gnu.org> | 2009-10-08 01:32:51 +0100 |
commit | e5a942312327b2ef428e7d2d7fc97b5150c7c04a (patch) | |
tree | fd81fa90e7923181957eb30dcbb964a2a29c5e9d /gcc/c-common.c | |
parent | 1afab7bdc313af774b7bf5bf61872c6416e48ee9 (diff) | |
download | gcc-e5a942312327b2ef428e7d2d7fc97b5150c7c04a.zip gcc-e5a942312327b2ef428e7d2d7fc97b5150c7c04a.tar.gz gcc-e5a942312327b2ef428e7d2d7fc97b5150c7c04a.tar.bz2 |
re PR c/41182 (Revision 145254 caused ICE: tree check: expected integer_cst, have nop_expr in tree_int_cst_lt, at tree.c:5259)
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:
* gcc.c-torture/compile/pr41182-1.c: New.
From-SVN: r152548
Diffstat (limited to 'gcc/c-common.c')
-rw-r--r-- | gcc/c-common.c | 41 |
1 files changed, 37 insertions, 4 deletions
diff --git a/gcc/c-common.c b/gcc/c-common.c index bf57cb8..fb2a84e 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; } |