2010-07-15  Jie Zhang  <jie@codesourcery.com>

	Backport from mainline (originally from Sourcery G++ 4.4):

	gcc/cp/
	2010-04-07  Jie Zhang  <jie@codesourcery.com>

	PR c++/42556
	* typeck2.c (split_nonconstant_init_1): Drop empty CONSTRUCTOR
	when all of its elements are non-constant and have been split out.

	gcc/testsuite/
	2010-04-07  Jie Zhang  <jie@codesourcery.com>

	PR c++/42556
	* g++.dg/init/pr42556.C: New test.

 2010-07-12  Yao Qi  <yao@codesourcery.com>
 
 	Merge from Sourcery G++ 4.4:

=== modified file 'gcc/cp/typeck2.c'
--- old/gcc/cp/typeck2.c	2010-02-23 18:32:20 +0000
+++ new/gcc/cp/typeck2.c	2010-07-30 14:05:57 +0000
@@ -549,13 +549,15 @@
    expression to which INIT should be assigned.  INIT is a CONSTRUCTOR.  */
 
 static void
-split_nonconstant_init_1 (tree dest, tree init)
+split_nonconstant_init_1 (tree dest, tree *initp)
 {
   unsigned HOST_WIDE_INT idx;
+  tree init = *initp;
   tree field_index, value;
   tree type = TREE_TYPE (dest);
   tree inner_type = NULL;
   bool array_type_p = false;
+  HOST_WIDE_INT num_type_elements, num_initialized_elements;
 
   switch (TREE_CODE (type))
     {
@@ -567,6 +569,7 @@
     case RECORD_TYPE:
     case UNION_TYPE:
     case QUAL_UNION_TYPE:
+      num_initialized_elements = 0;
       FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (init), idx,
 				field_index, value)
 	{
@@ -589,12 +592,13 @@
 		sub = build3 (COMPONENT_REF, inner_type, dest, field_index,
 			      NULL_TREE);
 
-	      split_nonconstant_init_1 (sub, value);
+	      split_nonconstant_init_1 (sub, &value);
 	    }
 	  else if (!initializer_constant_valid_p (value, inner_type))
 	    {
 	      tree code;
 	      tree sub;
+	      HOST_WIDE_INT inner_elements;
 
 	      /* FIXME: Ordered removal is O(1) so the whole function is
 		 worst-case quadratic. This could be fixed using an aside
@@ -617,9 +621,22 @@
 	      code = build2 (INIT_EXPR, inner_type, sub, value);
 	      code = build_stmt (input_location, EXPR_STMT, code);
 	      add_stmt (code);
+
+	      inner_elements = count_type_elements (inner_type, true);
+	      if (inner_elements < 0)
+		num_initialized_elements = -1;
+	      else if (num_initialized_elements >= 0)
+		num_initialized_elements += inner_elements;
 	      continue;
 	    }
 	}
+
+      num_type_elements = count_type_elements (type, true);
+      /* If all elements of the initializer are non-constant and
+	 have been split out, we don't need the empty CONSTRUCTOR.  */
+      if (num_type_elements > 0
+	  && num_type_elements == num_initialized_elements)
+	*initp = NULL;
       break;
 
     case VECTOR_TYPE:
@@ -655,7 +672,7 @@
   if (TREE_CODE (init) == CONSTRUCTOR)
     {
       code = push_stmt_list ();
-      split_nonconstant_init_1 (dest, init);
+      split_nonconstant_init_1 (dest, &init);
       code = pop_stmt_list (code);
       DECL_INITIAL (dest) = init;
       TREE_READONLY (dest) = 0;

=== added file 'gcc/testsuite/g++.dg/init/pr42556.C'
--- old/gcc/testsuite/g++.dg/init/pr42556.C	1970-01-01 00:00:00 +0000
+++ new/gcc/testsuite/g++.dg/init/pr42556.C	2010-07-30 14:05:57 +0000
@@ -0,0 +1,10 @@
+// { dg-do compile }
+// { dg-options "-fdump-tree-gimple" }
+
+void foo (int a, int b, int c, int d)
+{
+  int v[4] = {a, b, c, d};
+}
+
+// { dg-final { scan-tree-dump-not "v = {}"  "gimple" } }
+// { dg-final { cleanup-tree-dump "gimple" } }

