]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/51331 (bad code generated when explicitly calling auto-generated constructo...
authorJason Merrill <jason@redhat.com>
Fri, 16 Dec 2011 22:59:27 +0000 (17:59 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 16 Dec 2011 22:59:27 +0000 (17:59 -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: r182418

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 a2fa74895b16752e1133ded76f3df03d270a0c7a..6260496830ccd2cbd60f1cf451468f9138e2ba45 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-14  Jason Merrill  <jason@redhat.com>
 
        PR c++/51248
index 1c9a17b746a2b0815234d77bdfccfdd8481ffa9e..f14dd7804dc3e30c94c7c73886224635acc22b25 100644 (file)
@@ -464,7 +464,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
@@ -541,6 +548,10 @@ convert_to_base_statically (tree expr, tree base)
     {
       tree pointer_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);
+
       pointer_type = build_pointer_type (expr_type);
 
       /* We use fold_build2 and fold_convert below to simplify the trees
index f85a30b01fbe6057fde32a0092361dee6e2efa25..14766b648fbcaf06f0df03efc790ca69d79904d5 100644 (file)
@@ -141,7 +141,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 0e3d1f662fc0acc1ab433b76079014d01e33397c..3bfeedb5a73a7b68ed74da4849a97f24ecba3b2a 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-15  H.J. Lu  <hongjiu.lu@intel.com>
 
        Backport from mainline.
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;
+}