Commit c1aa4de7 by Mark Mitchell Committed by Mark Mitchell

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
parent c15398de
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
......
......@@ -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;
......
......@@ -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)
......
// 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 ());
}
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