This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]