Commit 5201931e by Jason Merrill Committed by Jason Merrill

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
parent 8844a2f5
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> 2004-08-06 Mark Mitchell <mark@codesourcery.com>
* config/arm/symbian.h (CC1_SPEC): Avoid passing duplicate options * config/arm/symbian.h (CC1_SPEC): Avoid passing duplicate options
......
...@@ -5378,6 +5378,9 @@ c_warn_unused_result (tree *top_p) ...@@ -5378,6 +5378,9 @@ c_warn_unused_result (tree *top_p)
break; break;
case CALL_EXPR: case CALL_EXPR:
if (TREE_USED (t))
break;
/* This is a naked call, as opposed to a CALL_EXPR nested inside /* This is a naked call, as opposed to a CALL_EXPR nested inside
a MODIFY_EXPR. All calls whose value is ignored should be a MODIFY_EXPR. All calls whose value is ignored should be
represented like this. Look for the attribute. */ represented like this. Look for the attribute. */
......
...@@ -1805,6 +1805,7 @@ gimplify_call_expr (tree *expr_p, tree *pre_p, bool want_value) ...@@ -1805,6 +1805,7 @@ gimplify_call_expr (tree *expr_p, tree *pre_p, bool want_value)
tree decl; tree decl;
tree arglist; tree arglist;
enum gimplify_status ret; enum gimplify_status ret;
tree slot;
#if defined ENABLE_CHECKING #if defined ENABLE_CHECKING
if (TREE_CODE (*expr_p) != CALL_EXPR) if (TREE_CODE (*expr_p) != CALL_EXPR)
...@@ -1867,6 +1868,19 @@ gimplify_call_expr (tree *expr_p, tree *pre_p, bool want_value) ...@@ -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, ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, NULL,
is_gimple_call_addr, fb_rvalue); 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) if (PUSH_ARGS_REVERSED)
TREE_OPERAND (*expr_p, 1) = nreverse (TREE_OPERAND (*expr_p, 1)); TREE_OPERAND (*expr_p, 1) = nreverse (TREE_OPERAND (*expr_p, 1));
for (arglist = TREE_OPERAND (*expr_p, 1); arglist; for (arglist = TREE_OPERAND (*expr_p, 1); arglist;
...@@ -1904,6 +1918,22 @@ gimplify_call_expr (tree *expr_p, tree *pre_p, bool want_value) ...@@ -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))) && (call_expr_flags (*expr_p) & (ECF_CONST | ECF_PURE)))
TREE_SIDE_EFFECTS (*expr_p) = 0; 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, ...@@ -2706,6 +2736,39 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p, tree *pre_p,
ret = GS_UNHANDLED; ret = GS_UNHANDLED;
break; 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: default:
ret = GS_UNHANDLED; ret = GS_UNHANDLED;
break; break;
...@@ -3021,12 +3084,14 @@ gimplify_addr_expr (tree *expr_p, tree *pre_p, tree *post_p) ...@@ -3021,12 +3084,14 @@ gimplify_addr_expr (tree *expr_p, tree *pre_p, tree *post_p)
default: default:
/* We use fb_either here because the C frontend sometimes takes /* 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, ret = gimplify_expr (&TREE_OPERAND (expr, 0), pre_p, post_p,
is_gimple_addressable, fb_either); is_gimple_addressable, fb_either);
if (ret != GS_ERROR) 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 so check for it here. It's not worth checking for the other
cases above. */ cases above. */
if (TREE_CODE (TREE_OPERAND (expr, 0)) == INDIRECT_REF) if (TREE_CODE (TREE_OPERAND (expr, 0)) == INDIRECT_REF)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment