The attached patch fixes PR c++/83588 - struct with two flexible
arrays causes an internal compiler error.  The ICE is caused by
the same assertion in varasm.c that has led to other similar
reports in the past:

  /* Given a non-empty initialization, this field had better
     be last.  Given a flexible array member, the next field
     on the chain is a TYPE_DECL of the enclosing struct.  */
  const_tree next = DECL_CHAIN (local->field);
  gcc_assert (!fieldsize || !next || TREE_CODE (next) != FIELD_DECL);

The fix is simply to also detect when a class defines more than
one flexible array member and treat the subsequent array as any
other member, and reject such class definitions to make sure they
never reach the assertion above.

Martin
PR c++/83588 - struct with two flexible arrays causes an internal compiler error

gcc/cp/ChangeLog:

	PR c++/83588
	* class.c (find_flexarrays): Make a record of multiple flexible array
	members.

gcc/testsuite/ChangeLog:

	PR c++/83588
	* g++.dg/ext/flexary28.C: New test.


Index: gcc/cp/class.c
===================================================================
--- gcc/cp/class.c	(revision 256674)
+++ gcc/cp/class.c	(working copy)
@@ -6566,14 +6566,17 @@ find_flexarrays (tree t, flexmems_t *fmem, bool ba
 	  /* Flexible array members have no upper bound.  */
 	  if (fmem->array)
 	    {
-	      /* Replace the zero-length array if it's been stored and
-		 reset the after pointer.  */
 	      if (TYPE_DOMAIN (TREE_TYPE (fmem->array)))
 		{
+		  /* Replace the zero-length array if it's been stored and
+		     reset the after pointer.  */
 		  fmem->after[bool (pun)] = NULL_TREE;
 		  fmem->array = fld;
 		  fmem->enclosing = pstr;
 		}
+	      else if (!fmem->after[bool (pun)])
+		/* Make a record of another flexible array member.  */
+		fmem->after[bool (pun)] = fld;
 	    }
 	  else
 	    {
Index: gcc/testsuite/g++.dg/ext/flexary28.C
===================================================================
--- gcc/testsuite/g++.dg/ext/flexary28.C	(nonexistent)
+++ gcc/testsuite/g++.dg/ext/flexary28.C	(working copy)
@@ -0,0 +1,46 @@
+// PR c++/83588 - struct with two flexible arrays causes an internal compiler
+// error
+// { dg-do compile }
+// { dg-options "-Wno-pedantic" }
+
+struct A {
+  int i;
+  int a[];          // { dg-error "flexible array member .A::a. not at end of .struct A." }
+  int b[];
+};
+
+struct B {
+  int i;
+  int a[];          // { dg-error "flexible array member .B::a. not at end of .struct B." }
+  int j;
+  int b[][2];
+};
+
+struct C {
+  int i;
+  struct {
+    int a[];        // { dg-error "flexible array member .C::<unnamed struct>::a. not at end of .struct C." }
+  };
+  int b[];
+};
+
+struct D {
+  int i;
+  struct {
+    int a[];        // { dg-error "flexible array member .D::<unnamed struct>::a. not at end of .struct D." }
+  } b[];
+  int c[];
+};
+
+struct E {
+  int i;
+  int a[0];
+  int b[];          // { dg-error "flexible array member .E::b. not at end of .struct E." }
+  int d[];
+};
+
+struct F {
+  int i;
+  int a[];          // { dg-error "flexible array member .F::a. not at end of .struct F." }
+  int b[], c[], d[];
+};

Reply via email to