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]

[tree-ssa] PATCH for c++/11266


The expander is careful to only expand a TARGET_EXPR the first time around;
later expansions just return the rtl for the slot.  This patch changes the
gimplifier to work similarly.

Of course, we shouldn't be see the same TARGET_EXPR in multiple places in
the testcase in the PR, but that's another bug which can be addressed
separately.

Tested athlon-pc-linux-gnu, applied to tree-ssa.  Test in
g++.dg/init/placement1.C.

2003-11-17  Jason Merrill  <jason@redhat.com>

	PR c++/11266
	* gimplify.c (gimple_add_tmp_var): Also make sure
	seen_in_bind_expr isn't set.
	(mostly_copy_tree_r): Don't copy a TARGET_EXPR.
	(gimplify_target_expr): Only expand a TARGET_EXPR the first time
	we see it.

*** gimplify.c.~1~	2003-11-15 16:30:50.000000000 -0500
--- gimplify.c	2003-11-17 11:14:46.000000000 -0500
*************** declare_tmp_vars (tree vars, tree scope)
*** 520,526 ****
  void
  gimple_add_tmp_var (tree tmp)
  {
!   if (TREE_CHAIN (tmp))
      abort ();
  
    DECL_CONTEXT (tmp) = current_function_decl;
--- 520,526 ----
  void
  gimple_add_tmp_var (tree tmp)
  {
!   if (TREE_CHAIN (tmp) || tmp->decl.seen_in_bind_expr)
      abort ();
  
    DECL_CONTEXT (tmp) = current_function_decl;
*************** annotate_all_with_locus (tree *stmt_p, l
*** 582,591 ****
      }
  }
  
! /* Similar to copy_tree_r() but do not copy SAVE_EXPR nodes.  These nodes
!    model computations that should only be done once.  If we were to unshare
!    something like SAVE_EXPR(i++), the gimplification process would create
!    wrong code.  */
  
  static tree
  mostly_copy_tree_r (tree *tp, int *walk_subtrees, void *data)
--- 582,591 ----
      }
  }
  
! /* Similar to copy_tree_r() but do not copy SAVE_EXPR or TARGET_EXPR nodes.
!    These nodes model computations that should only be done once.  If we
!    were to unshare something like SAVE_EXPR(i++), the gimplification
!    process would create wrong code.  */
  
  static tree
  mostly_copy_tree_r (tree *tp, int *walk_subtrees, void *data)
*************** mostly_copy_tree_r (tree *tp, int *walk_
*** 594,600 ****
    /* Don't unshare types, constants and SAVE_EXPR nodes.  */
    if (TREE_CODE_CLASS (code) == 't'
        || TREE_CODE_CLASS (code) == 'c'
!       || code == SAVE_EXPR
        /* We can't do anything sensible with a BLOCK used as an expression,
  	 but we also can't abort when we see it because of non-expression
  	 uses.  So just avert our eyes and cross our fingers.  Silly Java.  */
--- 594,600 ----
    /* Don't unshare types, constants and SAVE_EXPR nodes.  */
    if (TREE_CODE_CLASS (code) == 't'
        || TREE_CODE_CLASS (code) == 'c'
!       || code == SAVE_EXPR || code == TARGET_EXPR
        /* We can't do anything sensible with a BLOCK used as an expression,
  	 but we also can't abort when we see it because of non-expression
  	 uses.  So just avert our eyes and cross our fingers.  Silly Java.  */
*************** gimplify_target_expr (tree *expr_p, tree
*** 2672,2695 ****
    tree init = TARGET_EXPR_INITIAL (targ);
    enum gimplify_status ret;
  
!   /* TARGET_EXPR temps aren't part of the enclosing block, so add it to the
!      temps list.  */
!   gimple_add_tmp_var (temp);
! 
!   /* Build up the initialization and add it to pre_p.  */
!   init = build (MODIFY_EXPR, void_type_node, temp, init);
!   ret = gimplify_expr (&init, pre_p, post_p, is_gimple_stmt, fb_none);
!   if (ret == GS_ERROR)
!     return GS_ERROR;
  
!   append_to_statement_list (init, pre_p);
  
!   /* If needed, push the cleanup for the temp.  */
!   if (TARGET_EXPR_CLEANUP (targ))
!     {
!       gimplify_stmt (&TARGET_EXPR_CLEANUP (targ));
!       gimple_push_cleanup (TARGET_EXPR_CLEANUP (targ), pre_p);
      }
  
    *expr_p = temp;
    return GS_OK;
--- 2672,2705 ----
    tree init = TARGET_EXPR_INITIAL (targ);
    enum gimplify_status ret;
  
!   if (init)
!     {
!       /* TARGET_EXPR temps aren't part of the enclosing block, so add it to the
! 	 temps list.  */
!       gimple_add_tmp_var (temp);
! 
!       /* Build up the initialization and add it to pre_p.  */
!       init = build (MODIFY_EXPR, void_type_node, temp, init);
!       ret = gimplify_expr (&init, pre_p, post_p, is_gimple_stmt, fb_none);
!       if (ret == GS_ERROR)
! 	return GS_ERROR;
  
!       append_to_statement_list (init, pre_p);
  
!       /* If needed, push the cleanup for the temp.  */
!       if (TARGET_EXPR_CLEANUP (targ))
! 	{
! 	  gimplify_stmt (&TARGET_EXPR_CLEANUP (targ));
! 	  gimple_push_cleanup (TARGET_EXPR_CLEANUP (targ), pre_p);
! 	}
! 
!       /* Only expand this once.  */
!       TREE_OPERAND (targ, 3) = init;
!       TARGET_EXPR_INITIAL (targ) = NULL_TREE;
      }
+   else if (!temp->decl.seen_in_bind_expr)
+     /* We should have expanded this before.  */
+     abort ();
  
    *expr_p = temp;
    return GS_OK;

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