This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] PR c++/PR48035


On Fri, Mar 11, 2011 at 09:56:59AM -0500, Jason Merrill wrote:
> On 03/11/2011 03:01 AM, Jakub Jelinek wrote:
> >Do we need to redo parts of class.c anyway?  From what I understand, the
> >problematic vtbl pointers are at the end of the base types and DECL_SIZE
> >is set to the CLASSTYPE_AS_BASE type size, thus those pointers ought to
> >be at or beyond the containing field's size.
> >So, can't we simply skip subfields whose bit_position is equal or larger
> >to containing field's size?  Something like (works on the testcase from this
> >PR, otherwise untested):
> 
> Sure, that should work.  I had been thinking of stopping when we run
> out of fields in CLASSTYPE_AS_BASE, but your approach seems simpler.

It worked, here is what I've bootstrapped/regtested on x86_64-linux and
i686-linux.  Is that ok then?

> >Or, in the simplify_aggr_init case where the created tree is handed
> >immediately to the gimplifier, there is IMHO no point in initializing
> >all fields to zero when the gimplifier throws that immediately away again.
> 
> Unfortunately, pointers to data members make this not good enough:
> zero-initializing one means setting the bits to -1.  Though I
> suppose we could keep track of whether or not a class has a pointer
> to data member field somewhere (and therefore need to do this the
> hard way) and if not, just use an empty CONSTRUCTOR.

Np, we'd need to call a recursive function then to tell us if there
is a pointer to data member then.

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.

	* g++.dg/inherit/virtual8.C: New test.

--- gcc/cp/init.c.jj	2011-03-11 08:06:36.000000000 +0100
+++ gcc/cp/init.c	2011-03-11 08:40:29.321401994 +0100
@@ -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, 
 	  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, 
 	    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, 
   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].  */
 
--- gcc/testsuite/g++.dg/inherit/virtual8.C
+++ gcc/testsuite/g++.dg/inherit/virtual8.C
@@ -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;
+}


	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]