re PR c++/13387 (assignment to base class corrupts subclass)

cp:
	PR c++/13387
	* class.c (finish_struct_1): Compute mode and alias set for
	CLASSTYPE_AS_BASE.
	* call.c (build_over_call): Use CLASSTYPE_AS_BASE for trivial
	assignment of a class, as necessary.
	* cp-lang.c (cxx_get_alias_set): The alias set as a base is the
	same as for the complete type.
testsuite:
	PR c++/13387
	* g++.dg/expr/assign1.C: New test.

From-SVN: r74683
This commit is contained in:
Nathan Sidwell 2003-12-16 10:08:43 +00:00 committed by Nathan Sidwell
parent 0f30f285e4
commit a0c6873702
6 changed files with 76 additions and 1 deletions

View File

@ -1,5 +1,13 @@
2003-12-16 Nathan Sidwell <nathan@codesourcery.com>
PR c++/13387
* class.c (finish_struct_1): Compute mode and alias set for
CLASSTYPE_AS_BASE.
* call.c (build_over_call): Use CLASSTYPE_AS_BASE for trivial
assignment of a class, as necessary.
* cp-lang.c (cxx_get_alias_set): The alias set as a base is the
same as for the complete type.
PR c++/13242
C++ ABI change. Mangling template parameters of reference type
* mangle.c (write_template_args): Remove unreachable code.

View File

@ -4631,9 +4631,30 @@ build_over_call (struct z_candidate *cand, int flags)
{
tree to = stabilize_reference
(build_indirect_ref (TREE_VALUE (converted_args), 0));
tree type = TREE_TYPE (to);
tree as_base = CLASSTYPE_AS_BASE (type);
arg = build_indirect_ref (TREE_VALUE (TREE_CHAIN (converted_args)), 0);
val = build (MODIFY_EXPR, TREE_TYPE (to), to, arg);
if (tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (as_base)))
val = build (MODIFY_EXPR, TREE_TYPE (to), to, arg);
else
{
/* We must only copy the non-tail padding parts. Use
CLASSTYPE_AS_BASE for the bitwise copy. */
tree to_as_base, arg_as_base, base_ptr_type;
to = save_expr (to);
base_ptr_type = build_pointer_type (as_base);
to_as_base = build_indirect_ref
(build_nop (base_ptr_type, build_unary_op (ADDR_EXPR, to, 0)), 0);
arg_as_base = build_indirect_ref
(build_nop (base_ptr_type, build_unary_op (ADDR_EXPR, arg, 0)), 0);
val = build (MODIFY_EXPR, as_base, to_as_base, arg_as_base);
val = build (COMPOUND_EXPR, type, convert_to_void (val, NULL), to);
TREE_USED (val) = 1;
}
return val;
}

View File

@ -5052,6 +5052,10 @@ finish_struct_1 (tree t)
/* Layout the class itself. */
layout_class_type (t, &virtuals);
if (CLASSTYPE_AS_BASE (t) != t)
/* We use the base type for trivial assignments, and hence it
needs a mode. */
compute_record_mode (CLASSTYPE_AS_BASE (t));
/* Make sure that we get our own copy of the vfield FIELD_DECL. */
vfield = TYPE_VFIELD (t);

View File

@ -296,6 +296,11 @@ ok_to_generate_alias_set_for_type (tree t)
static HOST_WIDE_INT
cxx_get_alias_set (tree t)
{
if (CLASS_TYPE_P (t) && TYPE_CONTEXT (t) && CLASS_TYPE_P (TYPE_CONTEXT (t))
&& CLASSTYPE_AS_BASE (TYPE_CONTEXT (t)) == t)
/* The base variant of a type must be in the same alias set as the
complete type. */
t = TYPE_CONTEXT (t);
if (/* It's not yet safe to use alias sets for some classes in C++. */
!ok_to_generate_alias_set_for_type (t)

View File

@ -1,5 +1,8 @@
2003-12-16 Nathan Sidwell <nathan@codesourcery.com>
PR c++/13387
* g++.dg/expr/assign1.C: New test.
PR c++/13242
* g++.dg/abi/mangle19-1.C: New test.
* g++.dg/abi/mangle19-2.C: New test.

View File

@ -0,0 +1,34 @@
// { dg-do run }
// Contributed by Nathan Sidwell 15 Dec 2003 <nathan@codesourcery.com>
// Origin: Tasso Karkanis <Tasso.Karkanis@rogers.com>
// PR c++/13387. Clobbered tail padding of base
inline void *operator new (__SIZE_TYPE__, void *ptr)
{
return ptr;
}
struct Base {
Base() : i(0), c(0) {}
int i;
char c;
};
struct Sub : Base {
Sub () : d(0) {}
char d;
};
int main() {
Sub sub;
char base_alias[sizeof (Base)];
Base *base;
for (unsigned ix = sizeof base_alias; ix--;)
base_alias[ix] = 0x55;
base = new (&base_alias) Base ();
static_cast <Base &> (sub) = *base;
return sub.d;
}