re PR c++/13387 (assignment to base class corrupts subclass)
authorNathan Sidwell <nathan@codesourcery.com>
Tue, 16 Dec 2003 10:08:43 +0000 (10:08 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Tue, 16 Dec 2003 10:08:43 +0000 (10:08 +0000)
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
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/cp-lang.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/expr/assign1.C [new file with mode: 0644]

index a04a3d3..573604f 100644 (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.
index 99ba8b1..5634eea 100644 (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;
     }
 
index 55e9797..19b5ce6 100644 (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);
index 92e6b91..fdb1404 100644 (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)
index 496737d..0b91af7 100644 (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.
diff --git a/gcc/testsuite/g++.dg/expr/assign1.C b/gcc/testsuite/g++.dg/expr/assign1.C
new file mode 100644 (file)
index 0000000..7eb37e5
--- /dev/null
@@ -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; 
+}