From: Nathan Sidwell Date: Tue, 16 Dec 2003 10:08:43 +0000 (+0000) Subject: re PR c++/13387 (assignment to base class corrupts subclass) X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=a0c68737027348fb9ae1ff4a5a33a10d269962bb;p=platform%2Fupstream%2Fgcc.git 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 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index a04a3d3..573604f 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,13 @@ 2003-12-16 Nathan Sidwell + 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. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 99ba8b1..5634eea 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -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; } diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 55e9797..19b5ce6 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -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); diff --git a/gcc/cp/cp-lang.c b/gcc/cp/cp-lang.c index 92e6b91..fdb1404 100644 --- a/gcc/cp/cp-lang.c +++ b/gcc/cp/cp-lang.c @@ -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) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 496737d..0b91af7 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,8 @@ 2003-12-16 Nathan Sidwell + 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. diff --git a/gcc/testsuite/g++.dg/expr/assign1.C b/gcc/testsuite/g++.dg/expr/assign1.C new file mode 100644 index 0000000..7eb37e5 --- /dev/null +++ b/gcc/testsuite/g++.dg/expr/assign1.C @@ -0,0 +1,34 @@ +// { dg-do run } + +// Contributed by Nathan Sidwell 15 Dec 2003 +// Origin: Tasso Karkanis +// 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 (sub) = *base; + return sub.d; +}