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> 1999-05-16 Mark Mitchell <mark@codesourcery.com>
* decl2.c (build_expr_from_tree): Handle COMPONENT_REFs that * 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) else if (! real_lvalue_p (arg)
|| TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn))) || TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn)))
{ {
tree address;
tree to = stabilize_reference tree to = stabilize_reference
(build_indirect_ref (TREE_VALUE (args), 0)); (build_indirect_ref (TREE_VALUE (args), 0));
/* Don't copy the padding byte; it might not have been allocated /* If we're initializing an empty class, then we actually
if to is a base subobject. */ have to use a MODIFY_EXPR rather than an INIT_EXPR. The
if (is_empty_class (DECL_CLASS_CONTEXT (fn))) reason is that the dummy padding member in the target may
return build_unary_op not actually be allocated if TO is a base class
(ADDR_EXPR, build (COMPOUND_EXPR, TREE_TYPE (to), subobject. Since we've set TYPE_NONCOPIED_PARTS on the
cp_convert (void_type_node, arg), to), padding, a MODIFY_EXPR will preserve its value, which is
0); the right thing to do if it's not really padding at all.
val = build (INIT_EXPR, DECL_CONTEXT (fn), to, arg); 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; 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] 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); 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); val = build (MODIFY_EXPR, TREE_TYPE (to), to, arg);
TREE_SIDE_EFFECTS (val) = 1; TREE_SIDE_EFFECTS (val) = 1;
return val; return val;

View File

@ -3133,6 +3133,7 @@ finish_struct_1 (t, warn_anon)
int aggregate = 1; int aggregate = 1;
int empty = 1; int empty = 1;
int has_pointers = 0; int has_pointers = 0;
tree inline_friends;
if (warn_anon && code != UNION_TYPE && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))) if (warn_anon && code != UNION_TYPE && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
pedwarn ("anonymous class type not used to declare any objects"); 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) if (DECL_SIZE (x) != integer_zero_node)
empty = 0; 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) if (empty)
{ {
/* C++: do not let empty structures exist. */ /* C++: do not let empty structures exist. */
@ -3747,7 +3755,11 @@ finish_struct_1 (t, warn_anon)
(FIELD_DECL, NULL_TREE, char_type_node); (FIELD_DECL, NULL_TREE, char_type_node);
TREE_CHAIN (decl) = fields; TREE_CHAIN (decl) = fields;
TYPE_FIELDS (t) = decl; 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) if (n_baseclasses)
TYPE_FIELDS (t) = chainon (last_x, TYPE_FIELDS (t)); TYPE_FIELDS (t) = chainon (last_x, TYPE_FIELDS (t));
@ -4021,8 +4033,7 @@ finish_struct_1 (t, warn_anon)
} }
/* Write out inline function definitions. */ /* Write out inline function definitions. */
do_inline_function_hair (t, CLASSTYPE_INLINE_FRIENDS (t)); do_inline_function_hair (t, inline_friends);
CLASSTYPE_INLINE_FRIENDS (t) = 0;
if (CLASSTYPE_VSIZE (t) != 0) 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. */ /* 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 /* Before that can be done, we have to have FIELD_DECLs for them, and
a place to find them. */ 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) if (warn_nonvdtor && TYPE_HAS_DESTRUCTOR (t)
&& DECL_VINDEX (TREE_VEC_ELT (method_vec, 1)) == NULL_TREE) && 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 ());
}