From 6addabbbe815be8107207fcb6e2aa640e2e8c6ca Mon Sep 17 00:00:00 2001
From: Jie Zhang <jie@codesourcery.com>
Date: Wed, 7 Apr 2010 10:14:45 +0000
Subject: [PATCH] re PR c++/42556 (Unnecessary generation of a zero initializer
 for array with C++)

	cp/
	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.

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

From-SVN: r158047
---
 gcc/cp/ChangeLog                    |  6 ++++++
 gcc/cp/typeck2.c                    | 23 ++++++++++++++++++++---
 gcc/testsuite/ChangeLog             |  5 +++++
 gcc/testsuite/g++.dg/init/pr42556.C | 10 ++++++++++
 4 files changed, 41 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/init/pr42556.C

diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 782c674375d6..fd106914f5ee 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+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.
+
 2010-04-06  Taras Glek  <taras@mozilla.com>
 	    Jason Merrill  <jason@redhat.com>
 
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 7ec4374a7095..2610b28eca7e 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -549,13 +549,15 @@ cxx_incomplete_type_error (const_tree value, const_tree type)
    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 @@ split_nonconstant_init_1 (tree dest, tree init)
     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 @@ split_nonconstant_init_1 (tree dest, tree init)
 		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 @@ split_nonconstant_init_1 (tree dest, tree init)
 	      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 @@ split_nonconstant_init (tree dest, tree init)
   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;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index ce0a43956e42..cb2412ee8d39 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2010-04-07  Jie Zhang  <jie@codesourcery.com>
+
+	PR c++/42556
+	* g++.dg/init/pr42556.C: New test.
+
 2010-04-07  Dodji Seketeli  <dodji@redhat.com>
 
 	PR debug/43628
diff --git a/gcc/testsuite/g++.dg/init/pr42556.C b/gcc/testsuite/g++.dg/init/pr42556.C
new file mode 100644
index 000000000000..27370af79f61
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/pr42556.C
@@ -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" } }
-- 
GitLab