aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@codesourcery.com>2003-12-16 10:08:43 +0000
committerNathan Sidwell <nathan@gcc.gnu.org>2003-12-16 10:08:43 +0000
commita0c68737027348fb9ae1ff4a5a33a10d269962bb (patch)
treecdb6bff3438c48d90d9bc3062e8e3f8e2f8a81f6 /gcc/cp
parent0f30f285e44b335cef60431f418bda986f47df35 (diff)
downloadgcc-a0c68737027348fb9ae1ff4a5a33a10d269962bb.zip
gcc-a0c68737027348fb9ae1ff4a5a33a10d269962bb.tar.gz
gcc-a0c68737027348fb9ae1ff4a5a33a10d269962bb.tar.bz2
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
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog8
-rw-r--r--gcc/cp/call.c23
-rw-r--r--gcc/cp/class.c4
-rw-r--r--gcc/cp/cp-lang.c5
4 files changed, 39 insertions, 1 deletions
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 <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.
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)