This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
fix c++/16277
- From: Richard Henderson <rth at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 23 Jul 2004 15:55:25 -0700
- Subject: fix c++/16277
The primary bug was the failure to unshare TARGET when we built the
two MODIFY_EXPRs. When the first MODIFY_EXPR was subsequently
gimplified, the second MODIFY_EXPR was munged, resulting in the
observed use-before-set.
Given that TARGET can be arbitrarily complicated, it didn't seem
the best of ideas to just unshare it and be done. Thus the change
to gimplify it to a minimal lvalue.
Further, it seemed a good idea to push any assignment to a non-register
type down into the conditional, since that can eliminate the need for
an arbitrarily large temporary.
Tested on i686-linux.
r~
PR c++/16277
* gimplify.c (gimplify_cond_expr): Gimplify TARGET to a min_lval;
unshare it properly.
(gimplify_modify_expr_rhs): Push assignment from a conditional into
the conditional for all non-register types.
Index: gimplify.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gimplify.c,v
retrieving revision 2.52
diff -c -p -d -r2.52 gimplify.c
*** gimplify.c 20 Jul 2004 22:47:58 -0000 2.52
--- gimplify.c 23 Jul 2004 22:44:14 -0000
*************** static enum gimplify_status
*** 2191,2197 ****
gimplify_cond_expr (tree *expr_p, tree *pre_p, tree target)
{
tree expr = *expr_p;
! tree tmp, type;
enum gimplify_status ret;
type = TREE_TYPE (expr);
--- 2191,2197 ----
gimplify_cond_expr (tree *expr_p, tree *pre_p, tree target)
{
tree expr = *expr_p;
! tree tmp, tmp2, type;
enum gimplify_status ret;
type = TREE_TYPE (expr);
*************** gimplify_cond_expr (tree *expr_p, tree *
*** 2204,2215 ****
{
if (target)
{
tmp = target;
! ret = GS_OK;
}
else
{
! tmp = create_tmp_var (TREE_TYPE (expr), "iftmp");
ret = GS_ALL_DONE;
}
--- 2204,2219 ----
{
if (target)
{
+ ret = gimplify_expr (&target, pre_p, NULL,
+ is_gimple_min_lval, fb_lvalue);
+ if (ret != GS_ERROR)
+ ret = GS_OK;
tmp = target;
! tmp2 = unshare_expr (target);
}
else
{
! tmp2 = tmp = create_tmp_var (TREE_TYPE (expr), "iftmp");
ret = GS_ALL_DONE;
}
*************** gimplify_cond_expr (tree *expr_p, tree *
*** 2222,2236 ****
/* Build the else clause, 't1 = b;'. */
if (TREE_TYPE (TREE_OPERAND (expr, 2)) != void_type_node)
TREE_OPERAND (expr, 2)
! = build (MODIFY_EXPR, void_type_node, tmp, TREE_OPERAND (expr, 2));
TREE_TYPE (expr) = void_type_node;
recalculate_side_effects (expr);
! /* Move the COND_EXPR to the prequeue and use the temp in its place. */
gimplify_and_add (expr, pre_p);
- *expr_p = tmp;
return ret;
}
--- 2226,2240 ----
/* Build the else clause, 't1 = b;'. */
if (TREE_TYPE (TREE_OPERAND (expr, 2)) != void_type_node)
TREE_OPERAND (expr, 2)
! = build (MODIFY_EXPR, void_type_node, tmp2, TREE_OPERAND (expr, 2));
TREE_TYPE (expr) = void_type_node;
recalculate_side_effects (expr);
! /* Move the COND_EXPR to the prequeue. */
gimplify_and_add (expr, pre_p);
+ *expr_p = tmp;
return ret;
}
*************** gimplify_modify_expr_rhs (tree *expr_p,
*** 2689,2698 ****
return gimplify_init_constructor (expr_p, pre_p, post_p, want_value);
case COND_EXPR:
! /* If we're assigning from a ?: expression with ADDRESSABLE type, push
! the assignment down into the branches, since we can't generate a
! temporary of such a type. */
! if (TREE_ADDRESSABLE (TREE_TYPE (*from_p)))
{
*expr_p = *from_p;
return gimplify_cond_expr (expr_p, pre_p, *to_p);
--- 2693,2703 ----
return gimplify_init_constructor (expr_p, pre_p, post_p, want_value);
case COND_EXPR:
! /* If we're assigning to a non-register type, push the assignment
! down into the branches. This is mandatory for ADDRESSABLE types,
! since we cannot generate temporaries for such, but it saves a
! 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, *to_p);