[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