aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2004-08-07 12:11:10 -0400
committerJason Merrill <jason@gcc.gnu.org>2004-08-07 12:11:10 -0400
commit5201931ea147af4f55fe47ed879fbef5b3461ef0 (patch)
treeed52c7e668a41a71abd14d2bc80216a67ea6d0f5
parent8844a2f541582d58075af46362d57a1f75fc6eff (diff)
downloadgcc-5201931ea147af4f55fe47ed879fbef5b3461ef0.zip
gcc-5201931ea147af4f55fe47ed879fbef5b3461ef0.tar.gz
gcc-5201931ea147af4f55fe47ed879fbef5b3461ef0.tar.bz2
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
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/c-common.c3
-rw-r--r--gcc/gimplify.c69
3 files changed, 77 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a55a3d9..80dec91 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/c-common.c b/gcc/c-common.c
index c3dc4ea..868088f 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -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. */
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 53cf1fe..cd2a4a0 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -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)