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:
parent
8844a2f541
commit
5201931ea1
3 changed files with 77 additions and 2 deletions
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Reference in a new issue