From 5201931ea147af4f55fe47ed879fbef5b3461ef0 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Sat, 7 Aug 2004 12:11:10 -0400 Subject: [PATCH] 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 --- gcc/ChangeLog | 7 +++++ gcc/c-common.c | 3 +++ gcc/gimplify.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 77 insertions(+), 2 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a55a3d92921..80dec913224 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2004-08-07 Jason Merrill + + * 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 * config/arm/symbian.h (CC1_SPEC): Avoid passing duplicate options diff --git a/gcc/c-common.c b/gcc/c-common.c index c3dc4ea6359..868088f0e1c 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 53cf1feac32..cd2a4a0beec 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) -- 2.30.2