https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119001

--- Comment #4 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
So IMHO at least we want something like:
--- gcc/c/c-typeck.cc.jj        2025-02-13 14:10:52.934623189 +0100
+++ gcc/c/c-typeck.cc   2025-02-25 10:47:02.220272763 +0100
@@ -12124,6 +12124,42 @@ retry:
            warning (OPT_Wtraditional, "traditional C rejects initialization "
                     "of unions");

+         /* Error for non-static initialization of a flexible array member. 
*/
+         if (fieldcode == ARRAY_TYPE
+             && !require_constant_value
+             && TYPE_SIZE (fieldtype) == NULL_TREE)
+           {
+             error_init (loc, "non-static initialization of a flexible "
+                         "array member");
+             break;
+           }
+
+         /* Error for initialization of a flexible array member with
+            a string constant if the structure is in an array.  E.g.:
+            union U { int x; char y[]; };
+            union U s[] = { { 1, "foo" } };
+            is invalid.  */
+         if (string_flag
+             && fieldcode == ARRAY_TYPE
+             && constructor_depth > 1
+             && TYPE_SIZE (fieldtype) == NULL_TREE)
+           {
+             bool in_array_p = false;
+             for (struct constructor_stack *p = constructor_stack;
+                  p && p->type; p = p->next)
+               if (TREE_CODE (p->type) == ARRAY_TYPE)
+                 {
+                   in_array_p = true;
+                   break;
+                 }
+             if (in_array_p)
+               {
+                 error_init (loc, "initialization of flexible array "
+                             "member in a nested context");
+                 break;
+               }
+           }
+
          /* Accept a string constant to initialize a subarray.  */
          if (value.value != NULL_TREE
              && fieldcode == ARRAY_TYPE
--- gcc/varasm.cc.jj    2025-01-03 17:59:48.816160159 +0100
+++ gcc/varasm.cc       2025-02-25 10:52:08.043968775 +0100
@@ -5827,10 +5827,13 @@ output_constructor_regular_field (oc_loc
             and the FE splits them into dynamic initialization.  */
          gcc_checking_assert (fieldsize >= fldsize);
          /* 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.  */
+            be last except in unions.  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);
+         gcc_assert (!fieldsize
+                     || !next
+                     || TREE_CODE (next) != FIELD_DECL
+                     || TREE_CODE (local->type) == UNION_TYPE);
        }
       else
        fieldsize = tree_to_uhwi (DECL_SIZE_UNIT (local->field));
--- gcc/testsuite/gcc.dg/pr119001-1.c.jj        2025-02-25 11:06:07.717169471
+0100
+++ gcc/testsuite/gcc.dg/pr119001-1.c   2025-02-25 11:21:04.947577152 +0100
@@ -0,0 +1,35 @@
+/* PR c/119001 */
+/* { dg-do run } */
+/* { dg-options "" } */
+
+union U { char a[]; int i; };
+union U u = { "12345" };
+union U v = { .a = "6789" };
+union U w = { { 1, 2, 3, 4, 5, 6 } };
+union U x = { .a = { 7, 8, 9 } };
+union V { int i; char a[]; };
+union U y = { .a = "abcdefghijk" };
+union U z = { .a = { 10, 11, 12, 13, 14, 15, 16, 17 } };
+
+int
+main ()
+{
+  for (int i = 0; i < 6; ++i)
+    if (u.a[i] != "12345"[i])
+      __builtin_abort ();
+  for (int i = 0; i < 5; ++i)
+    if (v.a[i] != "6789"[i])
+      __builtin_abort ();
+  for (int i = 0; i < 6; ++i)
+    if (w.a[i] != i + 1)
+      __builtin_abort ();
+  for (int i = 0; i < 3; ++i)
+    if (x.a[i] != i + 7)
+      __builtin_abort ();
+  for (int i = 0; i < 12; ++i)
+    if (y.a[i] != "abcdefghijk"[i])
+      __builtin_abort ();
+  for (int i = 0; i < 8; ++i)
+    if (z.a[i] != i + 10)
+      __builtin_abort ();
+}
--- gcc/testsuite/gcc.dg/pr119001-2.c.jj        2025-02-25 11:06:28.124882967
+0100
+++ gcc/testsuite/gcc.dg/pr119001-2.c   2025-02-25 11:17:56.341223024 +0100
@@ -0,0 +1,12 @@
+/* PR c/119001 */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+union U { char a[]; int i; };
+union U u[1] = { { "12345" } };                        /* { dg-error
"initialization of flexible array member in a nested context" } */
+union U v[1] = { { .a = "6789" } };            /* { dg-error "initialization
of flexible array member in a nested context" } */
+union U w[1] = { { { 1, 2, 3, 4, 5, 6 } } };   /* { dg-error "initialization
of flexible array member in a nested context" } */
+union U x[1] = { { .a = { 7, 8, 9 } } };       /* { dg-error "initialization
of flexible array member in a nested context" } */
+union V { int i; char a[]; };
+union V y[1] = { { .a = "6789" } };            /* { dg-error "initialization
of flexible array member in a nested context" } */
+union V z[1] = { { .a = { 7, 8, 9 } } };       /* { dg-error "initialization
of flexible array member in a nested context" } */

But the pr119001-1.c testcase fails at runtime, for some reason w and x aren't
initialized properly, the initializers are as if they were {}.

Reply via email to