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

login
register
mail settings
Submitter Jason Merrill
Date Sept. 5, 2012, 4:05 a.m.
Message ID <5046CF99.8060504@redhat.com>
Download mbox | patch
Permalink /patch/181719/
State New
Headers show

Comments

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

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;
+}