call.c (build_over_call): Don't throw away initializations/copies of empty classes...

* call.c (build_over_call): Don't throw away
	initializations/copies of empty classes; use MODIFY_EXPR and
	INIT_EXPR as for non-empty classes.
	* class.c (finish_struct_1): Put the padding byte for an empty
	class on the TYPE_NONCOPIED_PARTS list for the class.

From-SVN: r26970
This commit is contained in:
Mark Mitchell 1999-05-17 07:42:26 +00:00 committed by Mark Mitchell
parent c15398de77
commit c1aa4de772
4 changed files with 71 additions and 19 deletions

View File

@ -1,3 +1,11 @@
1999-05-17 Mark Mitchell <mark@codesourcery.com>
* call.c (build_over_call): Don't throw away
initializations/copies of empty classes; use MODIFY_EXPR and
INIT_EXPR as for non-empty classes.
* class.c (finish_struct_1): Put the padding byte for an empty
class on the TYPE_NONCOPIED_PARTS list for the class.
1999-05-16 Mark Mitchell <mark@codesourcery.com>
* decl2.c (build_expr_from_tree): Handle COMPONENT_REFs that

View File

@ -3426,20 +3426,34 @@ build_over_call (cand, args, flags)
else if (! real_lvalue_p (arg)
|| TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn)))
{
tree address;
tree to = stabilize_reference
(build_indirect_ref (TREE_VALUE (args), 0));
/* Don't copy the padding byte; it might not have been allocated
if to is a base subobject. */
if (is_empty_class (DECL_CLASS_CONTEXT (fn)))
return build_unary_op
(ADDR_EXPR, build (COMPOUND_EXPR, TREE_TYPE (to),
cp_convert (void_type_node, arg), to),
0);
val = build (INIT_EXPR, DECL_CONTEXT (fn), to, arg);
/* If we're initializing an empty class, then we actually
have to use a MODIFY_EXPR rather than an INIT_EXPR. The
reason is that the dummy padding member in the target may
not actually be allocated if TO is a base class
subobject. Since we've set TYPE_NONCOPIED_PARTS on the
padding, a MODIFY_EXPR will preserve its value, which is
the right thing to do if it's not really padding at all.
It's not safe to just throw away the ARG if we're looking
at an empty class because the ARG might contain a
TARGET_EXPR which wants to be bound to TO. If it is not,
expand_expr will assign a dummy slot for the TARGET_EXPR,
and we will call a destructor for it, which is wrong,
because we will also destroy TO, but will never have
constructed it. */
val = build (is_empty_class (DECL_CLASS_CONTEXT (fn))
? MODIFY_EXPR : INIT_EXPR,
DECL_CONTEXT (fn), to, arg);
TREE_SIDE_EFFECTS (val) = 1;
return build_unary_op (ADDR_EXPR, val, 0);
address = build_unary_op (ADDR_EXPR, val, 0);
/* Avoid a warning about this expression, if the address is
never used. */
TREE_USED (address) = 1;
return address;
}
}
else if (DECL_NAME (fn) == ansi_opname[MODIFY_EXPR]
@ -3451,12 +3465,6 @@ build_over_call (cand, args, flags)
arg = build_indirect_ref (TREE_VALUE (TREE_CHAIN (converted_args)), 0);
/* Don't copy the padding byte; it might not have been allocated
if to is a base subobject. */
if (is_empty_class (DECL_CLASS_CONTEXT (fn)))
return build (COMPOUND_EXPR, TREE_TYPE (to),
cp_convert (void_type_node, arg), to);
val = build (MODIFY_EXPR, TREE_TYPE (to), to, arg);
TREE_SIDE_EFFECTS (val) = 1;
return val;

View File

@ -3133,6 +3133,7 @@ finish_struct_1 (t, warn_anon)
int aggregate = 1;
int empty = 1;
int has_pointers = 0;
tree inline_friends;
if (warn_anon && code != UNION_TYPE && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
pedwarn ("anonymous class type not used to declare any objects");
@ -3740,6 +3741,13 @@ finish_struct_1 (t, warn_anon)
if (DECL_SIZE (x) != integer_zero_node)
empty = 0;
}
/* CLASSTYPE_INLINE_FRIENDS is really TYPE_NONCOPIED_PARTS. Thus,
we have to save this before we start modifying
TYPE_NONCOPIED_PARTS. */
inline_friends = CLASSTYPE_INLINE_FRIENDS (t);
CLASSTYPE_INLINE_FRIENDS (t) = NULL_TREE;
if (empty)
{
/* C++: do not let empty structures exist. */
@ -3747,7 +3755,11 @@ finish_struct_1 (t, warn_anon)
(FIELD_DECL, NULL_TREE, char_type_node);
TREE_CHAIN (decl) = fields;
TYPE_FIELDS (t) = decl;
TYPE_NONCOPIED_PARTS (t)
= tree_cons (NULL_TREE, decl, TYPE_NONCOPIED_PARTS (t));
TREE_STATIC (TYPE_NONCOPIED_PARTS (t)) = 1;
}
if (n_baseclasses)
TYPE_FIELDS (t) = chainon (last_x, TYPE_FIELDS (t));
@ -4021,8 +4033,7 @@ finish_struct_1 (t, warn_anon)
}
/* Write out inline function definitions. */
do_inline_function_hair (t, CLASSTYPE_INLINE_FRIENDS (t));
CLASSTYPE_INLINE_FRIENDS (t) = 0;
do_inline_function_hair (t, inline_friends);
if (CLASSTYPE_VSIZE (t) != 0)
{
@ -4049,7 +4060,9 @@ finish_struct_1 (t, warn_anon)
/* In addition to this one, all the other vfields should be listed. */
/* Before that can be done, we have to have FIELD_DECLs for them, and
a place to find them. */
TYPE_NONCOPIED_PARTS (t) = build_tree_list (default_conversion (TYPE_BINFO_VTABLE (t)), vfield);
TYPE_NONCOPIED_PARTS (t)
= tree_cons (default_conversion (TYPE_BINFO_VTABLE (t)),
vfield, TYPE_NONCOPIED_PARTS (t));
if (warn_nonvdtor && TYPE_HAS_DESTRUCTOR (t)
&& DECL_VINDEX (TREE_VEC_ELT (method_vec, 1)) == NULL_TREE)

View File

@ -0,0 +1,23 @@
// Origin: Mark Mitchell <mark@codesourcery.com>
extern "C" void abort();
extern "C" void printf(const char*, ...);
int i;
struct A;
struct A* as[10];
struct A {
A () { as[i++] = this; }
A (const A&) { as[i++] = this; }
~A() { if (i == 0 || as[--i] != this) abort(); }
};
A f() { return A(); }
int main ()
{
A a (f ());
}