re PR c++/48035 (Mismatch on size of class when initializing hierarchy involving...
authorJakub Jelinek <jakub@redhat.com>
Fri, 11 Mar 2011 15:43:37 +0000 (16:43 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Fri, 11 Mar 2011 15:43:37 +0000 (16:43 +0100)
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

gcc/cp/ChangeLog
gcc/cp/init.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/inherit/virtual8.C [new file with mode: 0644]

index a4c394cbf35e556a97192455a6a146d3bda99bfe..da75a77c3a98013f27673ce0f3f26717cfae6e53 100644 (file)
@@ -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
index 56f66faffdd9816f8403423f9baba87c37bfceea..e1961c8ee77429ecd1c3d2c3357977c820c4a4cc 100644 (file)
@@ -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].  */
 
index 6169459bcef6d50c97b1aaa0af970d08ff2d52a8..7e7b9243da599425b9f824b01a9173a8705ff10d 100644 (file)
@@ -1,5 +1,8 @@
 2011-03-11  Jakub Jelinek  <jakub@redhat.com>
 
+       PR c++/48035
+       * g++.dg/inherit/virtual8.C: New test.
+
        PR middle-end/48044
        * gcc.dg/torture/pr48044.c: New test.
 
diff --git a/gcc/testsuite/g++.dg/inherit/virtual8.C b/gcc/testsuite/g++.dg/inherit/virtual8.C
new file mode 100644 (file)
index 0000000..4f6a119
--- /dev/null
@@ -0,0 +1,48 @@
+// PR c++/48035
+// { dg-do run }
+
+#include <new>
+#include <cstring>
+#include <cstdlib>
+
+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;
+}