aboutsummaryrefslogtreecommitdiff
path: root/gcc/c/c-fold.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/c/c-fold.c')
-rw-r--r--gcc/c/c-fold.c28
1 files changed, 23 insertions, 5 deletions
diff --git a/gcc/c/c-fold.c b/gcc/c/c-fold.c
index b060d76d..1baee44 100644
--- a/gcc/c/c-fold.c
+++ b/gcc/c/c-fold.c
@@ -120,12 +120,11 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
bool unused_p;
source_range old_range;
- /* Constants, declarations, statements, errors, SAVE_EXPRs and
- anything else not counted as an expression cannot usefully be
- folded further at this point. */
+ /* Constants, declarations, statements, errors, and anything else not
+ counted as an expression cannot usefully be folded further at this
+ point. */
if (!IS_EXPR_CODE_CLASS (kind)
- || kind == tcc_statement
- || code == SAVE_EXPR)
+ || kind == tcc_statement)
return expr;
if (IS_EXPR_CODE_CLASS (kind))
@@ -565,6 +564,25 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
appropriate in any particular case. */
gcc_unreachable ();
+ case SAVE_EXPR:
+ /* Make sure to fold the contents of a SAVE_EXPR exactly once. */
+ if (!SAVE_EXPR_FOLDED_P (expr))
+ {
+ op0 = TREE_OPERAND (expr, 0);
+ op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
+ maybe_const_itself, for_int_const);
+ /* Don't wrap the folded tree in a SAVE_EXPR if we don't
+ have to. */
+ if (tree_invariant_p (op0))
+ ret = op0;
+ else
+ {
+ TREE_OPERAND (expr, 0) = op0;
+ SAVE_EXPR_FOLDED_P (expr) = true;
+ }
+ }
+ goto out;
+
default:
/* Various codes may appear through folding built-in functions
and their arguments. */