[prev in list] [next in list] [prev in thread] [next in thread] 

List:       gcc-patches
Subject:    C++ PATCH for c++/8186
From:       Jason Merrill <jason () redhat ! com>
Date:       2002-10-31 21:32:45
[Download RAW message or body]

This bug was caused by an unfortunate interaction between
stabilize_throw_expr and the invisible reference handling.  We saved a copy
of the address of the temporary, but then dereferenced it again for
inlining; trying to use the result involved a bitwise copy, which was
caught by cp_expr_size.

Really, the rules in the standard for throwing in a throw-expression are
pretty bizarre.  I'll try to improve them such that stabilize_throw_expr
can just go away.

Test in g++.dg/eh/stabilize.C.  Tested i686-pc-linux-gnu.  Applied to
trunk.

2002-10-30  Jason Merrill  <jason@redhat.com>

	PR c++/8186
	* cp-tree.h (ADDR_IS_INVISIREF): New macro.
	* call.c (convert_for_arg_passing): Set it.
	* except.c (stabilize_throw_expr): Recurse for such an arg.


[Attachment #3 (text/x-patch)]

*** call.c.~1~	2002-10-29 13:23:26.000000000 -0500
--- call.c	2002-10-30 00:39:05.000000000 -0500
*************** convert_for_arg_passing (type, val)
*** 4277,4283 ****
  {
    /* Pass classes with copy ctors by invisible reference.  */
    if (TREE_ADDRESSABLE (type))
!     val = build1 (ADDR_EXPR, build_reference_type (type), val);
    else if (PROMOTE_PROTOTYPES
  	   && INTEGRAL_TYPE_P (type)
  	   && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
--- 4277,4286 ----
  {
    /* Pass classes with copy ctors by invisible reference.  */
    if (TREE_ADDRESSABLE (type))
!     {
!       val = build1 (ADDR_EXPR, build_reference_type (type), val);
!       ADDR_IS_INVISIREF (val) = 1;
!     }
    else if (PROMOTE_PROTOTYPES
  	   && INTEGRAL_TYPE_P (type)
  	   && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
*************** cp_convert_parm_for_inlining (parm, valu
*** 4295,4301 ****
    /* When inlining, we don't need to mess with invisible references, so
       undo the ADDR_EXPR.  */
    if (TREE_ADDRESSABLE (TREE_TYPE (parm)))
!     value = build_indirect_ref (value, NULL);
    return value;
  }
  
--- 4298,4308 ----
    /* When inlining, we don't need to mess with invisible references, so
       undo the ADDR_EXPR.  */
    if (TREE_ADDRESSABLE (TREE_TYPE (parm)))
!     {
!       value = TREE_OPERAND (value, 0);
!       if (TREE_CODE (value) != TARGET_EXPR)
! 	abort ();
!     }
    return value;
  }
  
*** cp-tree.h.~1~	2002-10-29 13:23:26.000000000 -0500
--- cp-tree.h	2002-10-29 23:15:20.000000000 -0500
*************** struct diagnostic_context;
*** 66,71 ****
--- 66,72 ----
        BINDING_HAS_LEVEL_P (in CPLUS_BINDING)
        BINFO_LOST_PRIMARY_P (in BINFO)
        TREE_PARMLIST (in TREE_LIST)
+       ADDR_IS_INVISIREF (in ADDR_EXPR)
     3: TYPE_USES_VIRTUAL_BASECLASSES (in a class TYPE).
        BINFO_VTABLE_PATH_MARKED.
        BINFO_PUSHDECLS_MARKED.
*************** struct lang_type GTY(())
*** 1666,1671 ****
--- 1667,1676 ----
  /* Nonzero for a parmlist means that this parmlist ended in ...  */
  #define PARMLIST_ELLIPSIS_P(NODE) TREE_LANG_FLAG_0 (NODE)
  
+ /* Nonzero if this ADDR_EXPR is used to implement the pass by invisible
+    reference calling convention.  */
+ #define ADDR_IS_INVISIREF(NODE) TREE_LANG_FLAG_2 (NODE)
+ 
  /* For FUNCTION_TYPE or METHOD_TYPE, a list of the exceptions that
     this type can raise.  Each TREE_VALUE is a _TYPE.  The TREE_VALUE
     will be NULL_TREE to indicate a throw specification of `()', or
*** except.c.~1~	2002-09-25 08:34:25.000000000 -0400
--- except.c	2002-10-30 07:57:01.000000000 -0500
*************** stabilize_throw_expr (exp, initp)
*** 599,610 ****
        init_expr = void_zero_node;
        for (; args; args = TREE_CHAIN (args))
  	{
  	  tree arg_init_expr;
! 	  tree newarg = stabilize_expr (TREE_VALUE (args), &arg_init_expr);
  
! 	  if (arg_init_expr != void_zero_node)
! 	    init_expr = build (COMPOUND_EXPR, void_type_node, arg_init_expr, init_expr);
! 	  *p = tree_cons (NULL_TREE, newarg, NULL_TREE);
  	  p = &TREE_CHAIN (*p);
  	}
        TREE_OPERAND (aggr_init, 1) = newargs;
--- 599,629 ----
        init_expr = void_zero_node;
        for (; args; args = TREE_CHAIN (args))
  	{
+ 	  tree arg = TREE_VALUE (args);
  	  tree arg_init_expr;
! 	  if (TREE_CODE (arg) == ADDR_EXPR
! 	      && ADDR_IS_INVISIREF (arg))
! 	    {
! 	      /* A sub-TARGET_EXPR.  Recurse; we can't wrap the actual call
! 		 without introducing an extra copy.  */
! 	      tree sub = TREE_OPERAND (arg, 0);
! 	      if (TREE_CODE (sub) != TARGET_EXPR)
! 		abort ();
! 	      sub = stabilize_throw_expr (sub, &arg_init_expr);
! 	      TREE_OPERAND (arg, 0) = sub;
! 	      if (TREE_SIDE_EFFECTS (arg_init_expr))
! 		init_expr = build (COMPOUND_EXPR, void_type_node, init_expr,
! 				   arg_init_expr);
! 	    }
! 	  else
! 	    {
! 	      arg = stabilize_expr (arg, &arg_init_expr);
  
! 	      if (TREE_SIDE_EFFECTS (arg_init_expr))
! 		init_expr = build (COMPOUND_EXPR, void_type_node, init_expr,
! 				   arg_init_expr);
! 	    }
! 	  *p = tree_cons (NULL_TREE, arg, NULL_TREE);
  	  p = &TREE_CHAIN (*p);
  	}
        TREE_OPERAND (aggr_init, 1) = newargs;


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic