My earlier patch to force layout when re-building an array type caused problems because we weren't setting TYPE_NEEDS_CONSTRUCTING at the same time. So this attacks the problem in a different way: the underlying issue here is that we're attaching a variant (which has been laid out) to a previously built main variant (which hasn't). So now, when we do that we make sure to copy the layout information to the older variants.

Tested x86_64-pc-linux-gnu, applying to trunk, 4.7 and 4.6.
commit 953241f451c969981f4fdecd9cdf90b133ada6d2
Author: Jason Merrill <ja...@redhat.com>
Date:   Wed Jan 2 09:53:19 2013 -0500

    	PR c++/55804
    	PR c++/55032
    	PR c++/55245
    	* tree.c (build_array_type_1): Revert earlier change.
    	* cp/tree.c (build_cplus_array_type): Copy layout information
    	to main variant if necessary.

diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index c430237..c658582 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -809,6 +809,15 @@ build_cplus_array_type (tree elt_type, tree index_type)
       t = build_array_type (elt_type, index_type);
     }
 
+  /* Push these needs up so that initialization takes place
+     more easily.  */
+  bool needs_ctor
+    = TYPE_NEEDS_CONSTRUCTING (TYPE_MAIN_VARIANT (elt_type));
+  TYPE_NEEDS_CONSTRUCTING (t) = needs_ctor;
+  bool needs_dtor
+    = TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TYPE_MAIN_VARIANT (elt_type));
+  TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) = needs_dtor;
+
   /* We want TYPE_MAIN_VARIANT of an array to strip cv-quals from the
      element type as well, so fix it up if needed.  */
   if (elt_type != TYPE_MAIN_VARIANT (elt_type))
@@ -818,6 +827,27 @@ build_cplus_array_type (tree elt_type, tree index_type)
 
       if (TYPE_MAIN_VARIANT (t) != m)
 	{
+	  if (COMPLETE_TYPE_P (t) && !COMPLETE_TYPE_P (m))
+	    {
+	      /* m was built before the element type was complete, so we
+		 also need to copy the layout info from t.  */
+	      tree size = TYPE_SIZE (t);
+	      tree size_unit = TYPE_SIZE_UNIT (t);
+	      unsigned int align = TYPE_ALIGN (t);
+	      unsigned int user_align = TYPE_USER_ALIGN (t);
+	      enum machine_mode mode = TYPE_MODE (t);
+	      for (tree var = m; var; var = TYPE_NEXT_VARIANT (var))
+		{
+		  TYPE_SIZE (var) = size;
+		  TYPE_SIZE_UNIT (var) = size_unit;
+		  TYPE_ALIGN (var) = align;
+		  TYPE_USER_ALIGN (var) = user_align;
+		  SET_TYPE_MODE (var, mode);
+		  TYPE_NEEDS_CONSTRUCTING (var) = needs_ctor;
+		  TYPE_HAS_NONTRIVIAL_DESTRUCTOR (var) = needs_dtor;
+		}
+	    }
+
 	  TYPE_MAIN_VARIANT (t) = m;
 	  TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m);
 	  TYPE_NEXT_VARIANT (m) = t;
@@ -828,12 +858,6 @@ build_cplus_array_type (tree elt_type, tree index_type)
   if (TYPE_SIZE (t) && EXPR_P (TYPE_SIZE (t)))
     TREE_NO_WARNING (TYPE_SIZE (t)) = 1;
 
-  /* Push these needs up so that initialization takes place
-     more easily.  */
-  TYPE_NEEDS_CONSTRUCTING (t)
-    = TYPE_NEEDS_CONSTRUCTING (TYPE_MAIN_VARIANT (elt_type));
-  TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)
-    = TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TYPE_MAIN_VARIANT (elt_type));
   return t;
 }
 
diff --git a/gcc/testsuite/g++.dg/init/array33.C b/gcc/testsuite/g++.dg/init/array33.C
new file mode 100644
index 0000000..4440d3d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/array33.C
@@ -0,0 +1,22 @@
+// PR c++/55804
+// { dg-do run }
+
+int t = 0;
+template <typename> struct vector {
+  vector() { t++; }
+};
+
+typedef vector<int> Arrays[1];
+class C
+{
+    vector<int> v_;
+    void Foo(const Arrays &);
+};
+Arrays a;
+
+int main(void)
+{
+  if (t!=1)
+    __builtin_abort ();
+  return 0;
+}
diff --git a/gcc/tree.c b/gcc/tree.c
index 429db49..7cacb2a 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -7505,12 +7505,7 @@ build_array_type_1 (tree elt_type, tree index_type, bool shared)
       hashval_t hashcode = iterative_hash_object (TYPE_HASH (elt_type), 0);
       if (index_type)
 	hashcode = iterative_hash_object (TYPE_HASH (index_type), hashcode);
-      tree old_t = t;
       t = type_hash_canon (hashcode, t);
-      if (t != old_t)
-	/* Lay it out again in case the element type has been completed since
-	   the array was added to the hash table.  */
-	layout_type (t);
     }
 
   if (TYPE_CANONICAL (t) == t)

Reply via email to