C++ PATCH for c++/54441 (infinite loop on ill-formed designated initializer)

Submitted by Jason Merrill on Sept. 5, 2012, 4:05 a.m.

Details

Message ID 5046CF99.8060504@redhat.com
State New
Headers show

Commit Message

Jason Merrill Sept. 5, 2012, 4:05 a.m.
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.

Patch hide | download patch | download mbox

commit b6c36df8a92bbbf8d8e741540c19329c8921c034
Author: Jason Merrill <jason@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;
+}