* c-common.h (RETURN_NULLIFIED_P): Lose.
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 10 Aug 2001 14:01:33 +0000 (14:01 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 10 Aug 2001 14:01:33 +0000 (14:01 +0000)
        * 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@44762 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/c-common.h
gcc/c-semantics.c
gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/optimize.c
gcc/cp/semantics.c
gcc/cp/typeck.c

index dbbe9d1..3e0bc8e 100644 (file)
@@ -1,3 +1,8 @@
+2001-08-08  Jason Merrill  <jason_merrill@redhat.com>
+
+       * c-common.h (RETURN_NULLIFIED_P): Lose.
+       * c-semantics.c (genrtl_return_stmt): Don't check it.
+
 2001-08-10  Richard Sandiford  <rsandifo@redhat.com>
 
        * config/mips/mips.c (mips_add_large_offset_to_sp): New function.
index 0ba64b1..edd0868 100644 (file)
@@ -32,7 +32,6 @@ Boston, MA 02111-1307, USA.  */
       SCOPE_BEGIN_P (in SCOPE_STMT)
       DECL_PRETTY_FUNCTION_P (in VAR_DECL)
       NEW_FOR_SCOPE_P (in FOR_STMT)
-      RETURN_NULLIFIED_P (in RETURN_STMT)
       ASM_INPUT_P (in ASM_STMT)
    1: C_DECLARED_LABEL_FLAG (in LABEL_DECL)
       STMT_IS_FULL_EXPR_P (in _STMT)
@@ -597,7 +596,6 @@ extern tree strip_array_types                   PARAMS ((tree));
    return statement, and whether it should be ignored when expanding
    (as opposed to inlining).  */
 #define RETURN_EXPR(NODE)       TREE_OPERAND (RETURN_STMT_CHECK (NODE), 0)
-#define RETURN_NULLIFIED_P(NODE) TREE_LANG_FLAG_0 (RETURN_STMT_CHECK (NODE))
 
 /* EXPR_STMT accessor. This gives the expression associated with an
    expression statement. */
index 2ee2647..e05ae76 100644 (file)
@@ -462,13 +462,7 @@ genrtl_return_stmt (stmt)
 {
   tree expr;
 
-  /* If RETURN_NULLIFIED_P is set, the frontend has arranged to set up
-     the return value separately, so just return the return value
-     itself.  This is used for the C++ named return value optimization.  */
-  if (RETURN_NULLIFIED_P (stmt))
-    expr = DECL_RESULT (current_function_decl);
-  else
-    expr = RETURN_EXPR (stmt);
+  expr = RETURN_EXPR (stmt);
 
   emit_line_note (input_filename, lineno);
   if (!expr)
index 02f3415..5f62396 100644 (file)
@@ -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
index fd079d2..cb90631 100644 (file)
@@ -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));
index 9ad8b76..8fffdb8 100644 (file)
@@ -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;
index 22e1eec..c0ebb99 100644 (file)
@@ -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);
 
index c7ce074..c295bde 100644 (file)
@@ -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.  */
index e38966f..d68e57e 100644 (file)
@@ -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;