From b01ed72c42fb20dfbe4170cc81fa99a14b35e4be Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Thu, 13 Oct 2011 14:02:53 -0400 Subject: [PATCH] re PR c++/48035 (Mismatch on size of class when initializing hierarchy involving virtual inheritance and empty base classes) PR c++/48035 * init.c (build_zero_init_1): Extracted from build_zero_init. Add FIELD_SIZE argument, if non-NULL and field bit_position as not smaller than that, don't add that field's initializer. Pass DECL_SIZE as last argument to build_zero_init_1 for DECL_FIELD_IS_BASE fields. (build_zero_init): Use build_zero_init_1. From-SVN: r179937 --- gcc/cp/ChangeLog | 13 ++++++ gcc/cp/init.c | 56 +++++++++++++++++++++---- gcc/testsuite/ChangeLog | 8 ++++ gcc/testsuite/g++.dg/inherit/virtual8.C | 48 +++++++++++++++++++++ 4 files changed, 116 insertions(+), 9 deletions(-) create mode 100644 gcc/testsuite/g++.dg/inherit/virtual8.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 2549c727f2cf..a5a834187d4e 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,16 @@ +2011-10-13 Jason Merrill + + Backported from 4.6 branch + 2011-03-11 Jakub Jelinek + + PR c++/48035 + * init.c (build_zero_init_1): Extracted from build_zero_init. + Add FIELD_SIZE argument, if non-NULL and field bit_position + as not smaller than that, don't add that field's initializer. + Pass DECL_SIZE as last argument to build_zero_init_1 + for DECL_FIELD_IS_BASE fields. + (build_zero_init): Use build_zero_init_1. + 2011-05-20 Jason Merrill PR c++/48873 diff --git a/gcc/cp/init.c b/gcc/cp/init.c index a06309b3f55b..4294acc80653 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -143,10 +143,13 @@ initialize_vtbl_ptrs (tree addr) is the number of elements in the array. If STATIC_STORAGE_P is TRUE, initializers are only generated for entities for which zero-initialization does not simply mean filling the storage with - zero bytes. */ + 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. */ -tree -build_zero_init (tree type, tree nelts, bool static_storage_p) +static tree +build_zero_init_1 (tree type, tree nelts, bool static_storage_p, + tree field_size) { tree init = NULL_TREE; @@ -191,15 +194,32 @@ build_zero_init (tree type, tree nelts, bool static_storage_p) if (TREE_CODE (field) != FIELD_DECL) continue; + /* Don't add virtual bases for base classes if they are beyond + the size of the current field, that means it is present + somewhere else in the object. */ + if (field_size) + { + tree bitpos = bit_position (field); + if (TREE_CODE (bitpos) == INTEGER_CST + && !tree_int_cst_lt (bitpos, field_size)) + continue; + } + /* Note that for class types there will be FIELD_DECLs corresponding to base classes as well. Thus, iterating over TYPE_FIELDs will result in correct initialization of all of the subobjects. */ if (!static_storage_p || !zero_init_p (TREE_TYPE (field))) { - tree value = build_zero_init (TREE_TYPE (field), - /*nelts=*/NULL_TREE, - static_storage_p); + tree new_field_size + = (DECL_FIELD_IS_BASE (field) + && DECL_SIZE (field) + && TREE_CODE (DECL_SIZE (field)) == INTEGER_CST) + ? DECL_SIZE (field) : NULL_TREE; + tree value = build_zero_init_1 (TREE_TYPE (field), + /*nelts=*/NULL_TREE, + static_storage_p, + new_field_size); if (value) CONSTRUCTOR_APPEND_ELT(v, field, value); } @@ -246,9 +266,9 @@ build_zero_init (tree type, tree nelts, bool static_storage_p) ce->index = build2 (RANGE_EXPR, sizetype, size_zero_node, max_index); - ce->value = build_zero_init (TREE_TYPE (type), - /*nelts=*/NULL_TREE, - static_storage_p); + ce->value = build_zero_init_1 (TREE_TYPE (type), + /*nelts=*/NULL_TREE, + static_storage_p, NULL_TREE); } /* Build a constructor to contain the initializations. */ @@ -266,6 +286,24 @@ build_zero_init (tree type, tree nelts, bool static_storage_p) return init; } +/* Return an expression for the zero-initialization of an object with + type T. This expression will either be a constant (in the case + that T is a scalar), or a CONSTRUCTOR (in the case that T is an + aggregate), or NULL (in the case that T does not require + initialization). In either case, the value can be used as + DECL_INITIAL for a decl of the indicated TYPE; it is a valid static + initializer. If NELTS is non-NULL, and TYPE is an ARRAY_TYPE, NELTS + is the number of elements in the array. If STATIC_STORAGE_P is + TRUE, initializers are only generated for entities for which + zero-initialization does not simply mean filling the storage with + zero bytes. */ + +tree +build_zero_init (tree type, tree nelts, bool static_storage_p) +{ + return build_zero_init_1 (type, nelts, static_storage_p, NULL_TREE); +} + /* Return a suitable initializer for value-initializing an object of type TYPE, as described in [dcl.init]. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 91596946f0a6..3fe28e698bbf 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2011-10-13 Jason Merrill + + Backported from 4.6 branch + 2011-03-11 Jakub Jelinek + + PR c++/48035 + * g++.dg/inherit/virtual8.C: New test. + 2011-09-01 Mikael Morin PR fortran/50050 diff --git a/gcc/testsuite/g++.dg/inherit/virtual8.C b/gcc/testsuite/g++.dg/inherit/virtual8.C new file mode 100644 index 000000000000..4f6a119b2879 --- /dev/null +++ b/gcc/testsuite/g++.dg/inherit/virtual8.C @@ -0,0 +1,48 @@ +// PR c++/48035 +// { dg-do run } + +#include +#include +#include + +struct A +{ + virtual void foo (void) {} + virtual ~A () {} +}; + +struct B : public A +{ + virtual ~B () {} +}; + +struct C +{ + virtual ~C () {} + int c; +}; + +struct D : public virtual B, public C +{ + virtual ~D () {} +}; + +struct E : public virtual D +{ + virtual ~E () {} +}; + +int +main () +{ + char *v = new char[sizeof (E) + 16]; + memset (v, 0x55, sizeof (E) + 16); + E *e = new (v) E (); + e->~E (); + + for (unsigned i = sizeof (E); i < sizeof (E) + 16; ++i) + if (v[i] != 0x55) + abort (); + + delete[] v; +} -- 2.47.2