diff options
author | Jason Merrill <jason@redhat.com> | 2011-12-16 17:34:39 -0500 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2011-12-16 17:34:39 -0500 |
commit | a8c1d899971e1b0c026b3f23fa27c5a041385655 (patch) | |
tree | a9e029ece57782eaabad6a6b34f5784f8dd04736 | |
parent | 20fb2c13c16829dc0246631d95281de92a65e35e (diff) | |
download | gcc-a8c1d899971e1b0c026b3f23fa27c5a041385655.zip gcc-a8c1d899971e1b0c026b3f23fa27c5a041385655.tar.gz gcc-a8c1d899971e1b0c026b3f23fa27c5a041385655.tar.bz2 |
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
-rw-r--r-- | gcc/cp/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/cp/class.c | 13 | ||||
-rw-r--r-- | gcc/cp/init.c | 4 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/init/value10.C | 27 |
5 files changed, 54 insertions, 2 deletions
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 <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 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 <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 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; +} |