When reshaping the initializer for a class, if we come to a zero-length array member, we don't consume any actual elements. But if an initializer designates that field, that means we keep trying to initialize that field and loop forever.

Fixed by checking for a designated initializer that doesn't get consumed.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit b6c36df8a92bbbf8d8e741540c19329c8921c034
Author: Jason Merrill <ja...@redhat.com>
Date:   Tue Sep 4 16:51:31 2012 -0400

    	PR c++/54441
    	* decl.c (reshape_init_class): Handle invalid initializer for
    	0-length array member.
    
    	* error.c (dump_type_suffix): Correct handling of 0-length arrays.

diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 8024373..b665fe8 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -5094,6 +5094,7 @@ reshape_init_class (tree type, reshape_iter *d, bool first_initializer_p,
   while (d->cur != d->end)
     {
       tree field_init;
+      constructor_elt *old_cur = d->cur;
 
       /* Handle designated initializers, as an extension.  */
       if (d->cur->index)
@@ -5130,6 +5131,15 @@ reshape_init_class (tree type, reshape_iter *d, bool first_initializer_p,
       if (field_init == error_mark_node)
 	return error_mark_node;
 
+      if (d->cur->index && d->cur == old_cur)
+	{
+	  /* This can happen with an invalid initializer for a flexible
+	     array member (c++/54441).  */
+	  if (complain & tf_error)
+	    error ("invalid initializer for %q#D", field);
+	  return error_mark_node;
+	}
+
       CONSTRUCTOR_APPEND_ELT (CONSTRUCTOR_ELTS (new_init), field, field_init);
 
       /* [dcl.init.aggr]
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 80a145d..1872d01 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -846,7 +846,9 @@ dump_type_suffix (tree t, int flags)
 	{
 	  tree dtype = TYPE_DOMAIN (t);
 	  tree max = TYPE_MAX_VALUE (dtype);
-	  if (host_integerp (max, 0))
+	  if (integer_all_onesp (max))
+	    pp_character (cxx_pp, '0');
+	  else if (host_integerp (max, 0))
 	    pp_wide_integer (cxx_pp, tree_low_cst (max, 0) + 1);
 	  else if (TREE_CODE (max) == MINUS_EXPR)
 	    dump_expr (TREE_OPERAND (max, 0),
diff --git a/gcc/testsuite/g++.dg/ext/flexary3.C b/gcc/testsuite/g++.dg/ext/flexary3.C
new file mode 100644
index 0000000..906877b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/flexary3.C
@@ -0,0 +1,10 @@
+// PR c++/54441
+// { dg-options "" }
+
+struct s { char c[]; };
+
+int main()
+{
+    struct s s = { .c = 0 };	// { dg-error "initializer" }
+    return 0;
+}

Reply via email to