PR mudflap/19319, c++/19317
authorJason Merrill <jason@redhat.com>
Thu, 17 Feb 2005 05:37:19 +0000 (00:37 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Thu, 17 Feb 2005 05:37:19 +0000 (00:37 -0500)
        PR mudflap/19319, c++/19317
        * gimplify.c (gimplify_modify_expr_rhs) [CALL_EXPR]: Make return
        slot explicit.

From-SVN: r95150

gcc/ChangeLog
gcc/gimplify.c

index 56fd26aba1d6f29dee892bdc86586f057fdb4d95..3a18b310debaa8fcaaab79986a330326e5cbdf42 100644 (file)
@@ -1,3 +1,9 @@
+2005-02-17  Jason Merrill  <jason@redhat.com>
+
+       PR mudflap/19319, c++/19317
+       * gimplify.c (gimplify_modify_expr_rhs) [CALL_EXPR]: Make return
+       slot explicit.
+
 2005-02-17  Gerald Pfeifer  <gerald@pfeifer.com>
 
        * doc/install.texi (Specific): Update link for Darwin-specific
 
 2005-02-13  Jason Merrill  <jason@redhat.com>
 
-       [reverted temporarily]
-       PR mudflap/19319
-       * gimplify.c (gimplify_modify_expr_rhs) [CALL_EXPR]: Make return
-       slot explicit.
-
        PR c++/16405
        * fold-const.c (fold_indirect_ref_1): Split out from...
        (build_fold_indirect_ref): Here.
index d461d776ee83da0072ce94c577e349ba00cc4fcd..89fd5c7e4f4658ddc5daecdf9e303e3156b94008 100644 (file)
@@ -2913,6 +2913,69 @@ 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 (aggregate_value_p (*from_p, *from_p))
+         {
+           tree init = *from_p;
+           tree fn = TREE_OPERAND (init, 0);
+           tree args = TREE_OPERAND (init, 1);
+           tree rettype = TREE_TYPE (TREE_TYPE (TREE_TYPE (fn)));
+           tree arg = *to_p;
+           tree type;
+
+           /* Only use the original target if *to_p isn't 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.  This is
+              c++/19317.  */
+           bool use_temp = !is_gimple_non_addressable (*to_p);
+
+           /* A CALL_EXPR with an explicit return slot argument should
+              never appear on the RHS of a MODIFY_EXPR.  */
+           if (CALL_EXPR_HAS_RETURN_SLOT_ADDR (*from_p))
+             abort ();
+
+           if (use_temp)
+             {
+               arg = create_tmp_var (rettype, "ret");
+               *from_p = arg;
+             }
+
+           type = TREE_TYPE (arg);
+           /* FIXME: Mark the address as not escaping.  */
+           lang_hooks.mark_addressable (arg);
+           arg = build1 (ADDR_EXPR, build_pointer_type (type), arg);
+           /* The return type might have different cv-quals from arg.  */
+           arg = convert (build_pointer_type (rettype), arg);
+           args = tree_cons (NULL_TREE, arg, args);
+           init = build3 (CALL_EXPR, rettype, fn, args, NULL_TREE);
+           CALL_EXPR_HAS_RETURN_SLOT_ADDR (init) = 1;
+           TREE_USED (init) = 1;
+
+           if (use_temp)
+             {
+               gimplify_and_add (init, pre_p);
+               ret = GS_OK;
+               break;
+             }
+           else if (want_value)
+             {
+               gimplify_and_add (init, pre_p);
+               *expr_p = *to_p;
+               return GS_OK;
+             }
+           else
+             {
+               *expr_p = init;
+               return GS_OK;
+             }
+         }
+       else
+         ret = GS_UNHANDLED;
+       break;
+
       default:
        ret = GS_UNHANDLED;
        break;