aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2001-08-10 10:01:33 -0400
committerJason Merrill <jason@gcc.gnu.org>2001-08-10 10:01:33 -0400
commit07b2f2fd6efdf33ab13eb31fc8ea38668dbf6ed6 (patch)
treed9f451da73883db76d0425e08382fce4bb154737 /gcc/cp
parent67070ffeb0f10bcc841e87756d18eb85de1ab8a8 (diff)
downloadgcc-07b2f2fd6efdf33ab13eb31fc8ea38668dbf6ed6.zip
gcc-07b2f2fd6efdf33ab13eb31fc8ea38668dbf6ed6.tar.gz
gcc-07b2f2fd6efdf33ab13eb31fc8ea38668dbf6ed6.tar.bz2
c-common.h (RETURN_NULLIFIED_P): Lose.
* c-common.h (RETURN_NULLIFIED_P): Lose. * c-semantics.c (genrtl_return_stmt): Don't check it. Support named return value optimization for inlines, too. * decl.c (finish_function): Nullify returns here. * semantics.c (genrtl_start_function): Not here. (cp_expand_stmt): Don't mess with CLEANUP_STMTs. (nullify_returns_r): No longer static. Just clear RETURN_EXPR. Also nullify the CLEANUP_STMT for the nrv. * cp-tree.h: Declare it. * optimize.c (declare_return_variable): Replace the nrv with the return variable. * typeck.c (check_return_expr): Be more flexible on alignment check. Ignore cv-quals when checking for a matching type. From-SVN: r44762
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog14
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/decl.c22
-rw-r--r--gcc/cp/optimize.c17
-rw-r--r--gcc/cp/semantics.c44
-rw-r--r--gcc/cp/typeck.c26
6 files changed, 90 insertions, 34 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 02f3415..5f62396 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,17 @@
+2001-08-07 Jason Merrill <jason_merrill@redhat.com>
+
+ Support named return value optimization for inlines, too.
+ * decl.c (finish_function): Nullify returns here.
+ * semantics.c (genrtl_start_function): Not here.
+ (cp_expand_stmt): Don't mess with CLEANUP_STMTs.
+ (nullify_returns_r): No longer static. Just clear RETURN_EXPR.
+ Also nullify the CLEANUP_STMT for the nrv.
+ * cp-tree.h: Declare it.
+ * optimize.c (declare_return_variable): Replace the nrv with the
+ return variable.
+ * typeck.c (check_return_expr): Be more flexible on alignment check.
+ Ignore cv-quals when checking for a matching type.
+
2001-08-09 Richard Henderson <rth@redhat.com>
* decl2.c (finish_objects): Use target hooks instead of
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index fd079d2..cb90631 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4129,6 +4129,7 @@ extern tree finish_typeof PARAMS ((tree));
extern void finish_decl_cleanup PARAMS ((tree, tree));
extern void finish_named_return_value PARAMS ((tree, tree));
extern void expand_body PARAMS ((tree));
+extern tree nullify_returns_r PARAMS ((tree *, int *, void *));
extern void do_pushlevel PARAMS ((void));
extern tree do_poplevel PARAMS ((void));
extern void finish_mem_initializers PARAMS ((tree));
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 9ad8b76..8fffdb8 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -13955,6 +13955,28 @@ finish_function (flags)
my_friendly_abort (122);
poplevel (1, 0, 1);
+ /* Set up the named return value optimization, if we can. Here, we
+ eliminate the copy from the nrv into the RESULT_DECL and any cleanup
+ for the nrv. genrtl_start_function and declare_return_variable
+ handle making the nrv and RESULT_DECL share space. */
+ if (current_function_return_value)
+ {
+ 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 (r != error_mark_node
+ && aggregate_value_p (TREE_TYPE (TREE_TYPE (fndecl))))
+ {
+ DECL_ALIGN (r) = DECL_ALIGN (DECL_RESULT (fndecl));
+ walk_tree_without_duplicates (&DECL_SAVED_TREE (fndecl),
+ nullify_returns_r, r);
+ }
+ else
+ /* Clear it so genrtl_start_function and declare_return_variable
+ know we're not optimizing. */
+ current_function_return_value = NULL_TREE;
+ }
+
/* Remember that we were in class scope. */
if (current_class_name)
ctype = current_class_type;
diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c
index 22e1eec..c0ebb99 100644
--- a/gcc/cp/optimize.c
+++ b/gcc/cp/optimize.c
@@ -602,6 +602,23 @@ declare_return_variable (id, use_stmt)
(splay_tree_key) result,
(splay_tree_value) var);
+ if (DECL_SAVED_FUNCTION_DATA (fn))
+ {
+ tree nrv = DECL_SAVED_FUNCTION_DATA (fn)->x_return_value;
+ if (nrv)
+ {
+ /* We have a named return value; copy the name and source
+ position so we can get reasonable debugging information, and
+ register the return variable as its equivalent. */
+ DECL_NAME (var) = DECL_NAME (nrv);
+ DECL_SOURCE_FILE (var) = DECL_SOURCE_FILE (nrv);
+ DECL_SOURCE_LINE (var) = DECL_SOURCE_LINE (nrv);
+ splay_tree_insert (id->decl_map,
+ (splay_tree_key) nrv,
+ (splay_tree_value) var);
+ }
+ }
+
/* Build the USE_STMT. */
*use_stmt = build_stmt (EXPR_STMT, var);
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index c7ce074..c295bde 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -50,7 +50,6 @@
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));
@@ -2196,11 +2195,7 @@ cp_expand_stmt (t)
switch (TREE_CODE (t))
{
case CLEANUP_STMT:
- if (CLEANUP_DECL (t)
- && CLEANUP_DECL (t) == current_function_return_value)
- /* Don't destroy the chosen named return value. */;
- else
- genrtl_decl_cleanup (CLEANUP_DECL (t), CLEANUP_EXPR (t));
+ genrtl_decl_cleanup (CLEANUP_DECL (t), CLEANUP_EXPR (t));
break;
case CTOR_STMT:
@@ -2504,20 +2499,27 @@ 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. */
+/* Helper function for walk_tree, used by finish_function to override all
+ the RETURN_STMTs and pertinent CLEANUP_STMTs for the named return
+ value optimization. */
-static tree
+tree
nullify_returns_r (tp, walk_subtrees, data)
tree *tp;
int *walk_subtrees;
- void *data ATTRIBUTE_UNUSED;
+ void *data;
{
- /* No need to walk into types. */
+ tree nrv = (tree) data;
+
+ /* No need to walk into types. There wouldn't be any need to walk into
+ non-statements, except that we have to consider STMT_EXPRs. */
if (TYPE_P (*tp))
*walk_subtrees = 0;
else if (TREE_CODE (*tp) == RETURN_STMT)
- RETURN_NULLIFIED_P (*tp) = 1;
+ RETURN_EXPR (*tp) = NULL_TREE;
+ else if (TREE_CODE (*tp) == CLEANUP_STMT
+ && CLEANUP_DECL (*tp) == nrv)
+ CLEANUP_EXPR (*tp) = NULL_TREE;
/* Keep iterating. */
return NULL_TREE;
@@ -2601,21 +2603,9 @@ genrtl_start_function (fn)
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);
- }
- }
+ /* Give our named return value the same RTL as our RESULT_DECL. */
+ if (current_function_return_value)
+ COPY_DECL_RTL (DECL_RESULT (fn), current_function_return_value);
}
/* Finish generating the RTL for FN. */
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index e38966f..d68e57e 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -6668,15 +6668,25 @@ check_return_expr (retval)
&& retval != current_class_ref)
cp_warning ("`operator=' should return a reference to `*this'");
- /* The fabled Named Return Value optimization: If this is a
- value-returning function that always returns the same local
- variable, remember it.
+ /* The fabled Named Return Value optimization, as per [class.copy]/15:
+
+ [...] For a function with a class return type, if the expression
+ in the return statement is the name of a local object, and the cv-
+ unqualified type of the local object is the same as the function
+ return type, an implementation is permitted to omit creating the tem-
+ porary object to hold the function return value [...]
+
+ So, if this is a value-returning function that always returns the same
+ local variable, remember it.
It might be nice to be more flexible, and choose the first suitable
variable even if the function sometimes returns something else, but
then we run the risk of clobbering the variable we chose if the other
returned expression uses the chosen variable somehow. And people expect
- this restriction, anyway. (jason 2000-11-19) */
+ this restriction, anyway. (jason 2000-11-19)
+
+ See finish_function, genrtl_start_function, and declare_return_variable
+ for other pieces of this optimization. */
if (fn_returns_value_p && flag_elide_constructors)
{
@@ -6687,9 +6697,11 @@ check_return_expr (retval)
&& DECL_CONTEXT (retval) == current_function_decl
&& ! TREE_STATIC (retval)
&& (DECL_ALIGN (retval)
- == DECL_ALIGN (DECL_RESULT (current_function_decl)))
- && same_type_p (TREE_TYPE (retval),
- TREE_TYPE (TREE_TYPE (current_function_decl))))
+ >= DECL_ALIGN (DECL_RESULT (current_function_decl)))
+ && same_type_p ((TYPE_MAIN_VARIANT
+ (TREE_TYPE (retval))),
+ (TYPE_MAIN_VARIANT
+ (TREE_TYPE (TREE_TYPE (current_function_decl))))))
current_function_return_value = retval;
else
current_function_return_value = error_mark_node;