Commit bab076f7 by Jason Merrill Committed by Jason Merrill

re PR c++/8186 (ICE in cp_expr_size, at cp/cp-lang.c:304)

        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.

From-SVN: r58696
parent ce02ba25
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.
2002-10-31 Mark Mitchell <mark@codesourcery.com> 2002-10-31 Mark Mitchell <mark@codesourcery.com>
* cp-tree.h (lang_decl_flags): Remove init_priority. * cp-tree.h (lang_decl_flags): Remove init_priority.
......
...@@ -4277,7 +4277,10 @@ convert_for_arg_passing (type, val) ...@@ -4277,7 +4277,10 @@ convert_for_arg_passing (type, val)
{ {
/* Pass classes with copy ctors by invisible reference. */ /* Pass classes with copy ctors by invisible reference. */
if (TREE_ADDRESSABLE (type)) if (TREE_ADDRESSABLE (type))
val = build1 (ADDR_EXPR, build_reference_type (type), val); {
val = build1 (ADDR_EXPR, build_reference_type (type), val);
ADDR_IS_INVISIREF (val) = 1;
}
else if (PROMOTE_PROTOTYPES else if (PROMOTE_PROTOTYPES
&& INTEGRAL_TYPE_P (type) && INTEGRAL_TYPE_P (type)
&& TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)) && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
...@@ -4295,7 +4298,11 @@ cp_convert_parm_for_inlining (parm, value, fn) ...@@ -4295,7 +4298,11 @@ cp_convert_parm_for_inlining (parm, value, fn)
/* When inlining, we don't need to mess with invisible references, so /* When inlining, we don't need to mess with invisible references, so
undo the ADDR_EXPR. */ undo the ADDR_EXPR. */
if (TREE_ADDRESSABLE (TREE_TYPE (parm))) if (TREE_ADDRESSABLE (TREE_TYPE (parm)))
value = build_indirect_ref (value, NULL); {
value = TREE_OPERAND (value, 0);
if (TREE_CODE (value) != TARGET_EXPR)
abort ();
}
return value; return value;
} }
......
...@@ -66,6 +66,7 @@ struct diagnostic_context; ...@@ -66,6 +66,7 @@ struct diagnostic_context;
BINDING_HAS_LEVEL_P (in CPLUS_BINDING) BINDING_HAS_LEVEL_P (in CPLUS_BINDING)
BINFO_LOST_PRIMARY_P (in BINFO) BINFO_LOST_PRIMARY_P (in BINFO)
TREE_PARMLIST (in TREE_LIST) TREE_PARMLIST (in TREE_LIST)
ADDR_IS_INVISIREF (in ADDR_EXPR)
3: TYPE_USES_VIRTUAL_BASECLASSES (in a class TYPE). 3: TYPE_USES_VIRTUAL_BASECLASSES (in a class TYPE).
BINFO_VTABLE_PATH_MARKED. BINFO_VTABLE_PATH_MARKED.
BINFO_PUSHDECLS_MARKED. BINFO_PUSHDECLS_MARKED.
...@@ -1673,6 +1674,10 @@ struct lang_type GTY(()) ...@@ -1673,6 +1674,10 @@ struct lang_type GTY(())
/* Nonzero for a parmlist means that this parmlist ended in ... */ /* Nonzero for a parmlist means that this parmlist ended in ... */
#define PARMLIST_ELLIPSIS_P(NODE) TREE_LANG_FLAG_0 (NODE) #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 /* 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 this type can raise. Each TREE_VALUE is a _TYPE. The TREE_VALUE
will be NULL_TREE to indicate a throw specification of `()', or will be NULL_TREE to indicate a throw specification of `()', or
......
...@@ -599,12 +599,31 @@ stabilize_throw_expr (exp, initp) ...@@ -599,12 +599,31 @@ stabilize_throw_expr (exp, initp)
init_expr = void_zero_node; init_expr = void_zero_node;
for (; args; args = TREE_CHAIN (args)) for (; args; args = TREE_CHAIN (args))
{ {
tree arg = TREE_VALUE (args);
tree arg_init_expr; tree arg_init_expr;
tree newarg = stabilize_expr (TREE_VALUE (args), &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 (arg_init_expr != void_zero_node) if (TREE_SIDE_EFFECTS (arg_init_expr))
init_expr = build (COMPOUND_EXPR, void_type_node, arg_init_expr, init_expr); init_expr = build (COMPOUND_EXPR, void_type_node, init_expr,
*p = tree_cons (NULL_TREE, newarg, NULL_TREE); arg_init_expr);
}
*p = tree_cons (NULL_TREE, arg, NULL_TREE);
p = &TREE_CHAIN (*p); p = &TREE_CHAIN (*p);
} }
TREE_OPERAND (aggr_init, 1) = newargs; TREE_OPERAND (aggr_init, 1) = newargs;
......
// PR c++/8186
// Bug: In f, convert_for_arg_passing wrapped the A TARGET_EXPR in an
// ADDR_EXPR for passing by invisible ref. stabilize_throw_expr copied the
// resulting pointer into a temporary. cp_convert_parm_for_inlining then
// dereferences it and tries to initialize B::am with the INDIRECT_REF,
// which calls for a bitwise copy. Which is broken.
// { dg-options "-O" }
struct A
{
A();
A(const A&);
A& operator=(const A&);
};
struct B {
A am;
B(A a) { am = a; }
};
void f ()
{
throw B(A());
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment