From a8c1d899971e1b0c026b3f23fa27c5a041385655 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Fri, 16 Dec 2011 17:34:39 -0500 Subject: [PATCH] re PR c++/51331 (bad code generated when explicitly calling auto-generated constructor of virtual base) 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 | 7 +++++++ gcc/cp/class.c | 13 ++++++++++++- gcc/cp/init.c | 4 +++- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/g++.dg/init/value10.C | 27 +++++++++++++++++++++++++++ 5 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/g++.dg/init/value10.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 5953866..ea5ebaa 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2011-12-16 Jason Merrill + + 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 PR c++/51458 diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 3cb76de..c96f7bf 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -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 diff --git a/gcc/cp/init.c b/gcc/cp/init.c index e93e82c..98a80e3 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -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, diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6413799..0cc6464 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2011-12-16 Jason Merrill + + PR c++/51331 + * g++.dg/init/value10.C: New. + 2011-12-16 Jakub Jelinek 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 index 0000000..2066410 --- /dev/null +++ b/gcc/testsuite/g++.dg/init/value10.C @@ -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; +} -- 2.7.4