diff options
author | Jakub Jelinek <jakub@redhat.com> | 2011-03-11 16:43:37 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2011-03-11 16:43:37 +0100 |
commit | e33eba75933fdd7bd895a3b35ef1b1b710ddbb13 (patch) | |
tree | 646fcf3880fcf55f5b06c27e45a7d9a15287445c /gcc/cp | |
parent | 4074f163fc39eedabb09f1ddcbd4c78bf55cb19b (diff) | |
download | gcc-e33eba75933fdd7bd895a3b35ef1b1b710ddbb13.zip gcc-e33eba75933fdd7bd895a3b35ef1b1b710ddbb13.tar.gz gcc-e33eba75933fdd7bd895a3b35ef1b1b710ddbb13.tar.bz2 |
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.
* g++.dg/inherit/virtual8.C: New test.
From-SVN: r170874
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/cp/init.c | 60 |
2 files changed, 59 insertions, 11 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index a4c394c..da75a77 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,13 @@ +2011-03-11 Jakub Jelinek <jakub@redhat.com> + + 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-03-10 Jason Merrill <jason@redhat.com> PR c++/48029 diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 56f66fa..e1961c8 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -1,7 +1,7 @@ /* Handle initialization things in C++. Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 - Free Software Foundation, Inc. + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, + 2011 Free Software Foundation, Inc. Contributed by Michael Tiemann (tiemann@cygnus.com) This file is part of GCC. @@ -140,10 +140,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; @@ -188,15 +191,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); } @@ -244,9 +264,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. */ @@ -264,6 +284,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]. */ |