re PR c++/51331 (bad code generated when explicitly calling auto-generated constructo...
authorJason Merrill <jason@redhat.com>
Fri, 16 Dec 2011 22:34:39 +0000 (17:34 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 16 Dec 2011 22:34:39 +0000 (17:34 -0500)
PR c++/51331
* class.c (convert_to_base_statically): Just call
build_simple_base_path.
(build_simple_base_path): Check field offset.

From-SVN: r182414

gcc/cp/ChangeLog
gcc/cp/class.c
gcc/cp/init.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/init/value10.C [new file with mode: 0644]

index 5953866..ea5ebaa 100644 (file)
@@ -1,3 +1,10 @@
+2011-12-16  Jason Merrill  <jason@redhat.com>
+
+       PR c++/51331
+       * class.c (convert_to_base_statically): Just call
+       build_simple_base_path.
+       (build_simple_base_path): Check field offset.
+
 2011-12-15  Jason Merrill  <jason@redhat.com>
 
        PR c++/51458
index 3cb76de..c96f7bf 100644 (file)
@@ -471,7 +471,14 @@ build_simple_base_path (tree expr, tree binfo)
     /* Is this the base field created by build_base_field?  */
     if (TREE_CODE (field) == FIELD_DECL
        && DECL_FIELD_IS_BASE (field)
-       && TREE_TYPE (field) == type)
+       && TREE_TYPE (field) == type
+       /* If we're looking for a field in the most-derived class,
+          also check the field offset; we can have two base fields
+          of the same type if one is an indirect virtual base and one
+          is a direct non-virtual base.  */
+       && (BINFO_INHERITANCE_CHAIN (d_binfo)
+           || tree_int_cst_equal (byte_position (field),
+                                  BINFO_OFFSET (binfo))))
       {
        /* We don't use build_class_member_access_expr here, as that
           has unnecessary checks, and more importantly results in
@@ -546,6 +553,10 @@ convert_to_base_statically (tree expr, tree base)
   expr_type = TREE_TYPE (expr);
   if (!SAME_BINFO_TYPE_P (BINFO_TYPE (base), expr_type))
     {
+      /* If this is a non-empty base, use a COMPONENT_REF.  */
+      if (!is_empty_class (BINFO_TYPE (base)))
+       return build_simple_base_path (expr, base);
+
       /* We use fold_build2 and fold_convert below to simplify the trees
         provided to the optimizers.  It is not safe to call these functions
         when processing a template because they do not handle C++-specific
index e93e82c..98a80e3 100644 (file)
@@ -140,7 +140,9 @@ initialize_vtbl_ptrs (tree addr)
    zero-initialization does not simply mean filling the storage with
    zero bytes.  FIELD_SIZE, if non-NULL, is the bit size of the field,
    subfields with bit positions at or above that bit size shouldn't
-   be added.  */
+   be added.  Note that this only works when the result is assigned
+   to a base COMPONENT_REF; if we only have a pointer to the base subobject,
+   expand_assignment will end up clearing the full size of TYPE.  */
 
 static tree
 build_zero_init_1 (tree type, tree nelts, bool static_storage_p,
index 6413799..0cc6464 100644 (file)
@@ -1,3 +1,8 @@
+2011-12-16  Jason Merrill  <jason@redhat.com>
+
+       PR c++/51331
+       * g++.dg/init/value10.C: New.
+
 2011-12-16  Jakub Jelinek  <jakub@redhat.com>
 
        PR testsuite/50803
diff --git a/gcc/testsuite/g++.dg/init/value10.C b/gcc/testsuite/g++.dg/init/value10.C
new file mode 100644 (file)
index 0000000..2066410
--- /dev/null
@@ -0,0 +1,27 @@
+// PR c++/51331
+// { dg-do run }
+
+struct A {
+  A(): x(10) {}
+  virtual ~A() {}
+
+  int x;
+};
+
+struct B: public virtual A {
+};
+
+struct C: public virtual A {
+};
+
+struct D: public B, virtual public C {
+  D(): B(), C() {}  // note an explicit call to C() which is auto-generated
+};
+
+int main() {
+  D* d = new D();
+
+  // Crashes here with the following message:
+  // *** glibc detected *** ./test: free(): invalid next size (fast)
+  delete d;
+}