diff options
Diffstat (limited to 'gcc/cp/semantics.c')
-rw-r--r-- | gcc/cp/semantics.c | 37 |
1 files changed, 36 insertions, 1 deletions
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 9dddf23..0dc392a 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -49,6 +49,7 @@ static tree maybe_convert_cond PARAMS ((tree)); static tree simplify_aggr_init_exprs_r PARAMS ((tree *, int *, void *)); +static tree nullify_returns_r PARAMS ((tree *, int *, void *)); static void deferred_type_access_control PARAMS ((void)); static void emit_associated_thunks PARAMS ((tree)); static void genrtl_try_block PARAMS ((tree)); @@ -2464,6 +2465,25 @@ expand_body (fn) timevar_pop (TV_EXPAND); } +/* Helper function for walk_tree, used by genrtl_start_function to override + all the RETURN_STMTs for the named return value optimization. */ + +static tree +nullify_returns_r (tp, walk_subtrees, data) + tree *tp; + int *walk_subtrees; + void *data ATTRIBUTE_UNUSED; +{ + /* No need to walk into types. */ + if (TYPE_P (*tp)) + *walk_subtrees = 0; + else if (TREE_CODE (*tp) == RETURN_STMT) + RETURN_NULLIFIED_P (*tp) = 1; + + /* Keep iterating. */ + return NULL_TREE; +} + /* Start generating the RTL for FN. */ static void @@ -2541,6 +2561,22 @@ genrtl_start_function (fn) /* Create a binding contour which can be used to catch cleanup-generated temporaries. */ expand_start_bindings (2); + + /* Set up the named return value optimization, if we can. */ + if (current_function_return_value + && current_function_return_value != error_mark_node) + { + tree r = current_function_return_value; + /* This is only worth doing for fns that return in memory--and + simpler, since we don't have to worry about promoted modes. */ + if (aggregate_value_p (TREE_TYPE (TREE_TYPE (fn)))) + { + COPY_DECL_RTL (DECL_RESULT (fn), r); + DECL_ALIGN (r) = DECL_ALIGN (DECL_RESULT (fn)); + walk_tree_without_duplicates (&DECL_SAVED_TREE (fn), + nullify_returns_r, NULL_TREE); + } + } } /* Finish generating the RTL for FN. */ @@ -2579,7 +2615,6 @@ genrtl_finish_function (fn) if (!dtor_label && !DECL_CONSTRUCTOR_P (fn) && return_label != NULL_RTX - && current_function_return_value == NULL_TREE && ! DECL_NAME (DECL_RESULT (current_function_decl))) no_return_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); |