aboutsummaryrefslogtreecommitdiff
path: root/gcc/gimplify.c
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2005-06-23 14:44:21 +0000
committerJason Merrill <jason@redhat.com>2005-06-23 14:44:21 +0000
commit5f12c4f29277c116e88fbd3ff13cec498a825074 (patch)
tree672b804a497a6d4d52b747f00969c6d7b30ebbfb /gcc/gimplify.c
parent440d82287d19363d2b7e02c53682d13ee8866f53 (diff)
PR c++/19317
Leave the return slot target in the MODIFY_EXPR rather than making it an argument, but only use it if the CALL_EXPR has a flag set. * tree.h (CALL_EXPR_HAS_RETURN_SLOT_ADDR): Rename to CALL_EXPR_RETURN_SLOT_OPT. * calls.c (expand_call): Adjust. * tree-inline.c (expand_call_inline): Adjust. * tree-pretty-print.c (dump_generic_node): Adjust. And set the flag as appropriate. * gimplify.c (gimplify_modify_expr_rhs): Set CALL_EXPR_HAS_RETURN_SLOT_ADDR where the LHS is obviously safe. * tree-nrv.c (execute_return_slot_opt): Set CALL_EXPR_HAS_RETURN_SLOT_ADDR based on escape analysis. * tree-pass.h: Declare pass_return_slot. * tree-optimize.c (init_tree_optimization_passes): Add it. * cp/semantics.c (simplify_aggr_init_expr): Use CALL_EXPR_RETURN_SLOT_OPT, not CALL_EXPR_HAS_RETURN_SLOT_ADDR. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@101269 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/gimplify.c')
-rw-r--r--gcc/gimplify.c40
1 files changed, 40 insertions, 0 deletions
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index df93bc5dde8..81512728dc5 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -3015,6 +3015,46 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p, tree *pre_p,
ret = GS_UNHANDLED;
break;
+ case CALL_EXPR:
+ /* For calls that return in memory, give *to_p as the CALL_EXPR's
+ return slot so that we don't generate a temporary. */
+ if (!CALL_EXPR_RETURN_SLOT_OPT (*from_p)
+ && aggregate_value_p (*from_p, *from_p))
+ {
+ bool use_target;
+
+ if (TREE_CODE (*to_p) == RESULT_DECL
+ && needs_to_live_in_memory (*to_p))
+ /* It's always OK to use the return slot directly. */
+ use_target = true;
+ else if (!is_gimple_non_addressable (*to_p))
+ /* Don't use the original target if it's already addressable;
+ if its address escapes, and the called function uses the
+ NRV optimization, a conforming program could see *to_p
+ change before the called function returns; see c++/19317.
+ When optimizing, the return_slot pass marks more functions
+ as safe after we have escape info. */
+ use_target = false;
+ else if (DECL_GIMPLE_FORMAL_TEMP_P (*to_p))
+ /* Don't use the original target if it's a formal temp; we
+ don't want to take their addresses. */
+ use_target = false;
+ else if (is_gimple_reg_type (TREE_TYPE (*to_p)))
+ /* Also don't force regs into memory. */
+ use_target = false;
+ else
+ use_target = true;
+
+ if (use_target)
+ {
+ CALL_EXPR_RETURN_SLOT_OPT (*from_p) = 1;
+ lang_hooks.mark_addressable (*to_p);
+ }
+ }
+
+ ret = GS_UNHANDLED;
+ break;
+
default:
ret = GS_UNHANDLED;
break;