aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2011-12-16 17:34:39 -0500
committerJason Merrill <jason@gcc.gnu.org>2011-12-16 17:34:39 -0500
commita8c1d899971e1b0c026b3f23fa27c5a041385655 (patch)
treea9e029ece57782eaabad6a6b34f5784f8dd04736
parent20fb2c13c16829dc0246631d95281de92a65e35e (diff)
downloadgcc-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/ChangeLog7
-rw-r--r--gcc/cp/class.c13
-rw-r--r--gcc/cp/init.c4
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/init/value10.C27
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;
+}