summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2006-02-09 09:54:36 +0000
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2006-02-09 09:54:36 +0000
commitcf6b103ecba3ec845e82cac95ce2693954438eec (patch)
tree2e7796711ab7dc7b1bc13550933b9b8d077c098e
parentf7bac623609f2c8ed2dbebebe91001b675a035e1 (diff)
downloadgcc-cf6b103ecba3ec845e82cac95ce2693954438eec.tar.gz
PR c++/25979
* tree.def: Elaborate on difference from MODIFY_EXPR. * doc/c-tree.texi (INIT_EXPR): Likewise. * gimplify.c (internal_get_tmp_var): Use INIT_EXPR. (gimplify_decl_expr, gimplify_init_ctor_eval): Likewise. (gimplify_target_expr): Likewise. (gimplify_cond_expr): Remove target handling. (gimplify_modify_expr): Don't clobber INIT_EXPR code here. (gimplify_expr): Clobber it here. (gimplify_modify_expr_rhs): Push assignment into COND_EXPR here. Do return slot optimization if we have an INIT_EXPR. PR tree-opt/24365 * tree-inline.c (declare_return_variable): Also clear DECL_COMPLEX_GIMPLE_REG_P as needed in the modify_dest case. PR c++/16405 * gimplify.c (gimplify_modify_expr_rhs): Re-enable *& handling. PR middle-end/22439 * gimplify.c (gimplify_one_sizepos): Fix typo. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@110789 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog24
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/cp-gimplify.c4
-rw-r--r--gcc/cp/typeck2.c2
-rw-r--r--gcc/doc/c-tree.texi5
-rw-r--r--gcc/gimplify.c105
-rw-r--r--gcc/testsuite/g++.dg/opt/temp1.C2
-rw-r--r--gcc/tree-inline.c3
-rw-r--r--gcc/tree.def3
9 files changed, 107 insertions, 48 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 9aef9b8a009..83b801fd6ba 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,27 @@
+2006-02-08 Jason Merrill <jason@redhat.com>
+
+ PR c++/25979
+ * tree.def: Elaborate on difference from MODIFY_EXPR.
+ * doc/c-tree.texi (INIT_EXPR): Likewise.
+ * gimplify.c (internal_get_tmp_var): Use INIT_EXPR.
+ (gimplify_decl_expr, gimplify_init_ctor_eval): Likewise.
+ (gimplify_target_expr): Likewise.
+ (gimplify_cond_expr): Remove target handling.
+ (gimplify_modify_expr): Don't clobber INIT_EXPR code here.
+ (gimplify_expr): Clobber it here.
+ (gimplify_modify_expr_rhs): Push assignment into COND_EXPR here.
+ Do return slot optimization if we have an INIT_EXPR.
+
+ PR tree-opt/24365
+ * tree-inline.c (declare_return_variable): Also clear
+ DECL_COMPLEX_GIMPLE_REG_P as needed in the modify_dest case.
+
+ PR c++/16405
+ * gimplify.c (gimplify_modify_expr_rhs): Re-enable *& handling.
+
+ PR middle-end/22439
+ * gimplify.c (gimplify_one_sizepos): Fix typo.
+
2006-02-08 Jeff Law <law@redhat.com>
PR tree-optimization/21417
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 947e080ae90..74071c91e90 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,10 @@
+2006-02-08 Jason Merrill <jason@redhat.com>
+
+ PR c++/25979
+ * cp-gimplify.c (cp_gimplify_expr): Don't call
+ cp_gimplify_init_expr for MODIFY_EXPRs.
+ * typeck2.c (split_nonconstant_init_1): Use INIT_EXPR.
+
2006-02-08 Volker Reichelt <reichelt@igpm.rwth-aachen.de>
PR c++/26071
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index 38838e734e6..a9fb7bf28e6 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -477,8 +477,10 @@ cp_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p)
ret = GS_OK;
break;
+ /* We used to do this for MODIFY_EXPR as well, but that's unsafe; the
+ LHS of an assignment might also be involved in the RHS, as in bug
+ 25979. */
case INIT_EXPR:
- case MODIFY_EXPR:
cp_gimplify_init_expr (expr_p, pre_p, post_p);
ret = GS_OK;
break;
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index fe5b3dff78e..49c58f8e51e 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -502,7 +502,7 @@ split_nonconstant_init_1 (tree dest, tree init)
sub = build3 (COMPONENT_REF, inner_type, dest, field_index,
NULL_TREE);
- code = build2 (MODIFY_EXPR, inner_type, sub, value);
+ code = build2 (INIT_EXPR, inner_type, sub, value);
code = build_stmt (EXPR_STMT, code);
add_stmt (code);
continue;
diff --git a/gcc/doc/c-tree.texi b/gcc/doc/c-tree.texi
index 5045b72eb60..62e7738054c 100644
--- a/gcc/doc/c-tree.texi
+++ b/gcc/doc/c-tree.texi
@@ -2350,7 +2350,10 @@ just like that for @samp{i = i + 3}.
@item INIT_EXPR
These nodes are just like @code{MODIFY_EXPR}, but are used only when a
-variable is initialized, rather than assigned to subsequently.
+variable is initialized, rather than assigned to subsequently. This
+means that we can assume that the target of the initialization is not
+used in computing its own value; any reference to the lhs in computing
+the rhs is undefined.
@item COMPONENT_REF
These nodes represent non-static data member accesses. The first
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index da800bba195..710569888ec 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -606,7 +606,7 @@ internal_get_tmp_var (tree val, tree *pre_p, tree *post_p, bool is_formal)
if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE)
DECL_COMPLEX_GIMPLE_REG_P (t) = 1;
- mod = build2 (MODIFY_EXPR, TREE_TYPE (t), t, val);
+ mod = build2 (INIT_EXPR, TREE_TYPE (t), t, val);
if (EXPR_HAS_LOCATION (val))
SET_EXPR_LOCUS (mod, EXPR_LOCUS (val));
@@ -1204,7 +1204,7 @@ gimplify_decl_expr (tree *stmt_p)
if (!TREE_STATIC (decl))
{
DECL_INITIAL (decl) = NULL_TREE;
- init = build2 (MODIFY_EXPR, void_type_node, decl, init);
+ init = build2 (INIT_EXPR, void_type_node, decl, init);
gimplify_and_add (init, stmt_p);
}
else
@@ -2341,14 +2341,10 @@ gimple_boolify (tree expr)
TARGET is the tree for T1 above.
PRE_P points to the list where side effects that must happen before
- *EXPR_P should be stored.
-
- POST_P points to the list where side effects that must happen after
- *EXPR_P should be stored. */
+ *EXPR_P should be stored. */
static enum gimplify_status
-gimplify_cond_expr (tree *expr_p, tree *pre_p, tree *post_p, tree target,
- fallback_t fallback)
+gimplify_cond_expr (tree *expr_p, tree *pre_p, fallback_t fallback)
{
tree expr = *expr_p;
tree tmp, tmp2, type;
@@ -2362,16 +2358,7 @@ gimplify_cond_expr (tree *expr_p, tree *pre_p, tree *post_p, tree target,
{
tree result;
- if (target)
- {
- ret = gimplify_expr (&target, pre_p, post_p,
- is_gimple_min_lval, fb_lvalue);
- if (ret != GS_ERROR)
- ret = GS_OK;
- result = tmp = target;
- tmp2 = unshare_expr (target);
- }
- else if ((fallback & fb_lvalue) == 0)
+ if ((fallback & fb_lvalue) == 0)
{
result = tmp2 = tmp = create_tmp_var (TREE_TYPE (expr), "iftmp");
ret = GS_ALL_DONE;
@@ -2836,7 +2823,7 @@ gimplify_init_ctor_eval (tree object, VEC(constructor_elt,gc) *elts,
pre_p, cleared);
else
{
- init = build2 (MODIFY_EXPR, TREE_TYPE (cref), cref, value);
+ init = build2 (INIT_EXPR, TREE_TYPE (cref), cref, value);
gimplify_and_add (init, pre_p);
}
}
@@ -3190,7 +3177,6 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p, tree *pre_p,
while (ret != GS_UNHANDLED)
switch (TREE_CODE (*from_p))
{
-#if 0
case INDIRECT_REF:
{
/* If we have code like
@@ -3212,7 +3198,6 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p, tree *pre_p,
ret = GS_UNHANDLED;
break;
}
-#endif
case TARGET_EXPR:
{
@@ -3257,9 +3242,36 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p, tree *pre_p,
copy in other cases as well. */
if (!is_gimple_reg_type (TREE_TYPE (*from_p)))
{
- *expr_p = *from_p;
- return gimplify_cond_expr (expr_p, pre_p, post_p, *to_p,
- fb_rvalue);
+ /* This code should mirror the code in gimplify_cond_expr. */
+ enum tree_code code = TREE_CODE (*expr_p);
+ tree cond = *from_p;
+ tree result = *to_p;
+
+ ret = gimplify_expr (&result, pre_p, post_p,
+ is_gimple_min_lval, fb_lvalue);
+ if (ret != GS_ERROR)
+ ret = GS_OK;
+
+ if (TREE_TYPE (TREE_OPERAND (cond, 1)) != void_type_node)
+ TREE_OPERAND (cond, 1)
+ = build2 (code, void_type_node, result,
+ TREE_OPERAND (cond, 1));
+ if (TREE_TYPE (TREE_OPERAND (cond, 2)) != void_type_node)
+ TREE_OPERAND (cond, 2)
+ = build2 (code, void_type_node, unshare_expr (result),
+ TREE_OPERAND (cond, 2));
+
+ TREE_TYPE (cond) = void_type_node;
+ recalculate_side_effects (cond);
+
+ if (want_value)
+ {
+ gimplify_and_add (cond, pre_p);
+ *expr_p = unshare_expr (result);
+ }
+ else
+ *expr_p = cond;
+ return ret;
}
else
ret = GS_UNHANDLED;
@@ -3273,11 +3285,26 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p, tree *pre_p,
{
bool use_target;
- if (TREE_CODE (*to_p) == RESULT_DECL
- && DECL_NAME (*to_p) == NULL_TREE
- && needs_to_live_in_memory (*to_p))
+ if (!(rhs_predicate_for (*to_p))(*from_p))
+ /* If we need a temporary, *to_p isn't accurate. */
+ use_target = false;
+ else if (TREE_CODE (*to_p) == RESULT_DECL
+ && DECL_NAME (*to_p) == NULL_TREE
+ && needs_to_live_in_memory (*to_p))
/* It's OK to use the return slot directly unless it's an NRV. */
use_target = true;
+ else if (is_gimple_reg_type (TREE_TYPE (*to_p)))
+ /* Don't force regs into memory. */
+ use_target = false;
+ else if (TREE_CODE (*to_p) == VAR_DECL
+ && DECL_GIMPLE_FORMAL_TEMP_P (*to_p))
+ /* Don't use the original target if it's a formal temp; we
+ don't want to take their addresses. */
+ use_target = false;
+ else if (TREE_CODE (*expr_p) == INIT_EXPR)
+ /* It's OK to use the target directly if it's being
+ initialized. */
+ use_target = true;
else if (!is_gimple_non_addressable (*to_p))
/* Don't use the original target if it's already addressable;
if its address escapes, and the called function uses the
@@ -3286,14 +3313,6 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p, tree *pre_p,
When optimizing, the return_slot pass marks more functions
as safe after we have escape info. */
use_target = false;
- else if (TREE_CODE (*to_p) != PARM_DECL
- && DECL_GIMPLE_FORMAL_TEMP_P (*to_p))
- /* Don't use the original target if it's a formal temp; we
- don't want to take their addresses. */
- use_target = false;
- else if (is_gimple_reg_type (TREE_TYPE (*to_p)))
- /* Also don't force regs into memory. */
- use_target = false;
else
use_target = true;
@@ -3379,10 +3398,6 @@ gimplify_modify_expr (tree *expr_p, tree *pre_p, tree *post_p, bool want_value)
gcc_assert (TREE_CODE (*expr_p) == MODIFY_EXPR
|| TREE_CODE (*expr_p) == INIT_EXPR);
- /* The distinction between MODIFY_EXPR and INIT_EXPR is no longer useful. */
- if (TREE_CODE (*expr_p) == INIT_EXPR)
- TREE_SET_CODE (*expr_p, MODIFY_EXPR);
-
/* For zero sized types only gimplify the left hand side and right hand side
as statements and throw away the assignment. */
if (zero_sized_type (TREE_TYPE (*from_p)))
@@ -4072,7 +4087,7 @@ gimplify_target_expr (tree *expr_p, tree *pre_p, tree *post_p)
gimplify_bind_expr (&init, temp, pre_p);
if (init != temp)
{
- init = build2 (MODIFY_EXPR, void_type_node, temp, init);
+ init = build2 (INIT_EXPR, void_type_node, temp, init);
ret = gimplify_expr (&init, pre_p, post_p, is_gimple_stmt,
fb_none);
}
@@ -5216,8 +5231,7 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p,
break;
case COND_EXPR:
- ret = gimplify_cond_expr (expr_p, pre_p, post_p, NULL_TREE,
- fallback);
+ ret = gimplify_cond_expr (expr_p, pre_p, fallback);
/* C99 code may assign to an array in a structure value of a
conditional expression, and this has undefined behavior
only on execution, so create a temporary if an lvalue is
@@ -5253,6 +5267,11 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p,
case INIT_EXPR:
ret = gimplify_modify_expr (expr_p, pre_p, post_p,
fallback != fb_none);
+
+ /* The distinction between MODIFY_EXPR and INIT_EXPR is no longer
+ useful. */
+ if (*expr_p && TREE_CODE (*expr_p) == INIT_EXPR)
+ TREE_SET_CODE (*expr_p, MODIFY_EXPR);
break;
case TRUTH_ANDIF_EXPR:
@@ -5889,7 +5908,7 @@ gimplify_one_sizepos (tree *expr_p, tree *stmt_p)
*expr_p = create_tmp_var (type, NULL);
tmp = build1 (NOP_EXPR, type, expr);
- tmp = build2 (MODIFY_EXPR, type, *expr_p, expr);
+ tmp = build2 (MODIFY_EXPR, type, *expr_p, tmp);
if (EXPR_HAS_LOCATION (expr))
SET_EXPR_LOCUS (tmp, EXPR_LOCUS (expr));
else
diff --git a/gcc/testsuite/g++.dg/opt/temp1.C b/gcc/testsuite/g++.dg/opt/temp1.C
index 6b0e2f3906d..b822dc464fe 100644
--- a/gcc/testsuite/g++.dg/opt/temp1.C
+++ b/gcc/testsuite/g++.dg/opt/temp1.C
@@ -1,6 +1,6 @@
// PR c++/16405
// { dg-options "-O2" }
-// { dg-do run { xfail *-*-* } }
+// { dg-do run }
// There should be exactly one temporary generated for the code in "f"
// below when optimizing -- for the result of "b + c". We have no
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 07085b104b1..f9ce09bbe35 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -1222,6 +1222,9 @@ declare_return_variable (copy_body_data *id, tree return_slot_addr,
use_it = false;
else if (is_global_var (base_m))
use_it = false;
+ else if (TREE_CODE (TREE_TYPE (base_m)) == COMPLEX_TYPE
+ && !DECL_COMPLEX_GIMPLE_REG_P (result))
+ DECL_COMPLEX_GIMPLE_REG_P (base_m) = 0;
else if (!TREE_ADDRESSABLE (base_m))
use_it = true;
}
diff --git a/gcc/tree.def b/gcc/tree.def
index bc227e20346..14c15a76d5c 100644
--- a/gcc/tree.def
+++ b/gcc/tree.def
@@ -465,7 +465,8 @@ DEFTREECODE (COMPOUND_EXPR, "compound_expr", tcc_expression, 2)
DEFTREECODE (MODIFY_EXPR, "modify_expr", tcc_expression, 2)
/* Initialization expression. Operand 0 is the variable to initialize;
- Operand 1 is the initializer. */
+ Operand 1 is the initializer. This differs from MODIFY_EXPR in that any
+ reference to the referent of operand 0 within operand 1 is undefined. */
DEFTREECODE (INIT_EXPR, "init_expr", tcc_expression, 2)
/* For TARGET_EXPR, operand 0 is the target of an initialization,