OSDN Git Service

* gimplify.c (gimplify_call_expr): Make return in memory explicit.
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 7 Aug 2004 16:11:10 +0000 (16:11 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 7 Aug 2004 16:11:10 +0000 (16:11 +0000)
        (gimplify_modify_expr_rhs): Likewise.
        * c-common.c (c_warn_unused_result): Check TREE_USED before
        warning about a CALL_EXPR with an unused value.

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

gcc/ChangeLog
gcc/c-common.c
gcc/gimplify.c

index a55a3d9..80dec91 100644 (file)
@@ -1,3 +1,10 @@
+2004-08-07  Jason Merrill  <jason@redhat.com>
+
+       * gimplify.c (gimplify_call_expr): Make return in memory explicit.
+       (gimplify_modify_expr_rhs): Likewise.
+       * c-common.c (c_warn_unused_result): Check TREE_USED before
+       warning about a CALL_EXPR with an unused value.
+
 2004-08-06  Mark Mitchell  <mark@codesourcery.com>
 
        * config/arm/symbian.h (CC1_SPEC): Avoid passing duplicate options
 2004-08-06  Mark Mitchell  <mark@codesourcery.com>
 
        * config/arm/symbian.h (CC1_SPEC): Avoid passing duplicate options
index c3dc4ea..868088f 100644 (file)
@@ -5378,6 +5378,9 @@ c_warn_unused_result (tree *top_p)
       break;
 
     case CALL_EXPR:
       break;
 
     case CALL_EXPR:
+      if (TREE_USED (t))
+       break;
+
       /* This is a naked call, as opposed to a CALL_EXPR nested inside
         a MODIFY_EXPR.  All calls whose value is ignored should be
         represented like this.  Look for the attribute.  */
       /* This is a naked call, as opposed to a CALL_EXPR nested inside
         a MODIFY_EXPR.  All calls whose value is ignored should be
         represented like this.  Look for the attribute.  */
index 53cf1fe..cd2a4a0 100644 (file)
@@ -1805,6 +1805,7 @@ gimplify_call_expr (tree *expr_p, tree *pre_p, bool want_value)
   tree decl;
   tree arglist;
   enum gimplify_status ret;
   tree decl;
   tree arglist;
   enum gimplify_status ret;
+  tree slot;
 
 #if defined ENABLE_CHECKING
   if (TREE_CODE (*expr_p) != CALL_EXPR)
 
 #if defined ENABLE_CHECKING
   if (TREE_CODE (*expr_p) != CALL_EXPR)
@@ -1867,6 +1868,19 @@ gimplify_call_expr (tree *expr_p, tree *pre_p, bool want_value)
   ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, NULL,
                       is_gimple_call_addr, fb_rvalue);
 
   ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, NULL,
                       is_gimple_call_addr, fb_rvalue);
 
+  /* Make the return slot explicit if it isn't already.  */
+  if (aggregate_value_p (*expr_p, decl)
+      && !CALL_EXPR_HAS_RETURN_SLOT_ADDR (*expr_p))
+    {
+      slot = create_tmp_var (TREE_TYPE (*expr_p), NULL);
+      arglist = build_fold_addr_expr (slot);
+      arglist = tree_cons (NULL_TREE, arglist, TREE_OPERAND (*expr_p, 1));
+      TREE_OPERAND (*expr_p, 1) = arglist;
+      CALL_EXPR_HAS_RETURN_SLOT_ADDR (*expr_p) = 1;
+    }
+  else
+    slot = NULL_TREE;
+
   if (PUSH_ARGS_REVERSED)
     TREE_OPERAND (*expr_p, 1) = nreverse (TREE_OPERAND (*expr_p, 1));
   for (arglist = TREE_OPERAND (*expr_p, 1); arglist;
   if (PUSH_ARGS_REVERSED)
     TREE_OPERAND (*expr_p, 1) = nreverse (TREE_OPERAND (*expr_p, 1));
   for (arglist = TREE_OPERAND (*expr_p, 1); arglist;
@@ -1904,6 +1918,22 @@ gimplify_call_expr (tree *expr_p, tree *pre_p, bool want_value)
       && (call_expr_flags (*expr_p) & (ECF_CONST | ECF_PURE)))
     TREE_SIDE_EFFECTS (*expr_p) = 0;
 
       && (call_expr_flags (*expr_p) & (ECF_CONST | ECF_PURE)))
     TREE_SIDE_EFFECTS (*expr_p) = 0;
 
+  /* If we have a return slot, use it in the containing expression.  */
+  if (want_value && CALL_EXPR_HAS_RETURN_SLOT_ADDR (*expr_p))
+    {
+      /* Don't warn about an unused return value.  */
+      TREE_USED (*expr_p) = 1;
+
+      if (slot == NULL_TREE)
+       {
+         slot = TREE_OPERAND (*expr_p, 1);
+         slot = TREE_VALUE (slot);
+         slot = build_fold_indirect_ref (slot);
+       }
+      append_to_statement_list (*expr_p, pre_p);
+      *expr_p = slot;
+    }
+
   return ret;
 }
 
   return ret;
 }
 
@@ -2706,6 +2736,39 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p, tree *pre_p,
          ret = GS_UNHANDLED;
        break;
 
          ret = GS_UNHANDLED;
        break;
 
+      case CALL_EXPR:
+       /* Transform 'a = f();' to 'f(&a), a' if f returns in memory.  */
+       if (aggregate_value_p (*from_p, *from_p))
+         {
+           tree arg;
+           if (CALL_EXPR_HAS_RETURN_SLOT_ADDR (*from_p))
+             abort ();
+
+           ret = gimplify_expr (to_p, pre_p, post_p, is_gimple_lvalue,
+                                fb_lvalue);
+           if (ret == GS_ERROR)
+             return ret;
+
+           arg = build_fold_addr_expr (*to_p);
+           arg = tree_cons (NULL_TREE, arg, TREE_OPERAND (*from_p, 1));
+           TREE_OPERAND (*from_p, 1) = arg;
+           CALL_EXPR_HAS_RETURN_SLOT_ADDR (*from_p) = 1;
+           /* Don't warn about an unused return value.  */
+           TREE_USED (*from_p) = 1;
+
+           if (want_value)
+             {
+               gimplify_and_add (*from_p, pre_p);
+               *expr_p = *to_p;
+             }
+           else
+             *expr_p = *from_p;
+           return GS_OK;
+         }
+       else
+         ret = GS_UNHANDLED;
+       break;
+
       default:
        ret = GS_UNHANDLED;
        break;
       default:
        ret = GS_UNHANDLED;
        break;
@@ -3021,12 +3084,14 @@ gimplify_addr_expr (tree *expr_p, tree *pre_p, tree *post_p)
 
     default:
       /* We use fb_either here because the C frontend sometimes takes
 
     default:
       /* We use fb_either here because the C frontend sometimes takes
-        the address of a call that returns a struct.  */
+        the address of a call that returns a struct; see
+        gcc.dg/c99-array-lval-1.c.  The gimplifier will correctly make
+        the implied temporary explicit.  */
       ret = gimplify_expr (&TREE_OPERAND (expr, 0), pre_p, post_p,
                           is_gimple_addressable, fb_either);
       if (ret != GS_ERROR)
        {
       ret = gimplify_expr (&TREE_OPERAND (expr, 0), pre_p, post_p,
                           is_gimple_addressable, fb_either);
       if (ret != GS_ERROR)
        {
-         /* The above may have made an INDIRECT ref (e.g, Ada's NULL_EXPR),
+         /* The above may have made an INDIRECT_REF (e.g, Ada's NULL_EXPR),
             so check for it here.  It's not worth checking for the other
             cases above.  */
          if (TREE_CODE (TREE_OPERAND (expr, 0)) == INDIRECT_REF)
             so check for it here.  It's not worth checking for the other
             cases above.  */
          if (TREE_CODE (TREE_OPERAND (expr, 0)) == INDIRECT_REF)