From a0c68737027348fb9ae1ff4a5a33a10d269962bb Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Tue, 16 Dec 2003 10:08:43 +0000 Subject: 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 --- gcc/cp/ChangeLog | 8 ++++++++ gcc/cp/call.c | 23 ++++++++++++++++++++++- gcc/cp/class.c | 4 ++++ gcc/cp/cp-lang.c | 5 +++++ 4 files changed, 39 insertions(+), 1 deletion(-) (limited to 'gcc/cp') 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..5634eea6 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) -- cgit v1.1