gimplify.c (gimplify_call_expr): Make return in memory explicit.

* 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.

From-SVN: r85671
This commit is contained in:
Jason Merrill 2004-08-07 12:11:10 -04:00 committed by Jason Merrill
parent 8844a2f541
commit 5201931ea1
3 changed files with 77 additions and 2 deletions

View 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

View File

@ -5378,6 +5378,9 @@ c_warn_unused_result (tree *top_p)
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. */

View 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 slot;
#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);
/* 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;
@ -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;
/* 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;
}
@ -2706,6 +2736,39 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p, tree *pre_p,
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;
@ -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
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)
{
/* 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)