diff options
author | Jason Merrill <jason@redhat.com> | 2011-11-12 19:44:39 -0500 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2011-11-12 19:44:39 -0500 |
commit | d0ad58f94e22dcf877cc359fe8f07e30836c7467 (patch) | |
tree | 27cac8d3632c8a697d809b3cfff114f8ef5675e8 /gcc/gimplify.c | |
parent | f2628dce2494cefe0144f733c930d6b3b2edf728 (diff) | |
download | gcc-d0ad58f94e22dcf877cc359fe8f07e30836c7467.zip gcc-d0ad58f94e22dcf877cc359fe8f07e30836c7467.tar.gz gcc-d0ad58f94e22dcf877cc359fe8f07e30836c7467.tar.bz2 |
re PR c++/51060 (Temporary object stack space is not re-used)
PR c++/51060
* gimplify.c (gimplify_target_expr): Add a clobber to the cleanup.
(gimplify_modify_expr): Don't try to simplify it.
* cp/cp-gimplify.c (cp_gimplify_expr): Leave clobbers alone.
From-SVN: r181332
Diffstat (limited to 'gcc/gimplify.c')
-rw-r--r-- | gcc/gimplify.c | 38 |
1 files changed, 36 insertions, 2 deletions
diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 9845b69..cfe6696 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -4554,6 +4554,16 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, gcc_assert (TREE_CODE (*expr_p) == MODIFY_EXPR || TREE_CODE (*expr_p) == INIT_EXPR); + /* Trying to simplify a clobber using normal logic doesn't work, + so handle it here. */ + if (TREE_CLOBBER_P (*from_p)) + { + gcc_assert (!want_value && TREE_CODE (*to_p) == VAR_DECL); + gimplify_seq_add_stmt (pre_p, gimple_build_assign (*to_p, *from_p)); + *expr_p = NULL; + return GS_ALL_DONE; + } + /* Insert pointer conversions required by the middle-end that are not required by the frontend. This fixes middle-end type checking for for example gcc.dg/redecl-6.c. */ @@ -5335,6 +5345,8 @@ gimplify_target_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) if (init) { + tree cleanup = NULL_TREE; + /* TARGET_EXPR temps aren't part of the enclosing block, so add it to the temps list. Handle also variable length TARGET_EXPRs. */ if (TREE_CODE (DECL_SIZE (temp)) != INTEGER_CST) @@ -5369,8 +5381,30 @@ gimplify_target_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) /* If needed, push the cleanup for the temp. */ if (TARGET_EXPR_CLEANUP (targ)) - gimple_push_cleanup (temp, TARGET_EXPR_CLEANUP (targ), - CLEANUP_EH_ONLY (targ), pre_p); + { + if (CLEANUP_EH_ONLY (targ)) + gimple_push_cleanup (temp, TARGET_EXPR_CLEANUP (targ), + CLEANUP_EH_ONLY (targ), pre_p); + else + cleanup = TARGET_EXPR_CLEANUP (targ); + } + + /* Add a clobber for the temporary going out of scope, like + gimplify_bind_expr. */ + if (needs_to_live_in_memory (temp)) + { + tree clobber = build_constructor (TREE_TYPE (temp), NULL); + TREE_THIS_VOLATILE (clobber) = true; + clobber = build2 (MODIFY_EXPR, TREE_TYPE (temp), temp, clobber); + if (cleanup) + cleanup = build2 (COMPOUND_EXPR, void_type_node, cleanup, + clobber); + else + cleanup = clobber; + } + + if (cleanup) + gimple_push_cleanup (temp, cleanup, false, pre_p); /* Only expand this once. */ TREE_OPERAND (targ, 3) = init; |