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:
parent
0f30f285e4
commit
a0c6873702
6 changed files with 76 additions and 1 deletions
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
|
34
gcc/testsuite/g++.dg/expr/assign1.C
Normal file
34
gcc/testsuite/g++.dg/expr/assign1.C
Normal 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;
|
||||
}
|
Loading…
Add table
Reference in a new issue