commit e3c92cd26597fea326d06a17e029d5b2c72e0e6c
Author: Jason Merrill <jason@redhat.com>
Date: Fri Dec 16 13:54:35 2011 -0500
PR c++/51331
* class.c (convert_to_base_statically): Just call
build_simple_base_path.
(build_simple_base_path): Check field offset.
@@ -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
new file mode 100644
@@ -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;
+}