Hi, Jakub, Thanks a lot for fixing this issues.
Qing > On Feb 26, 2025, at 03:53, Jakub Jelinek <ja...@redhat.com> wrote: > > Hi! > > r15-209 allowed flexible array members inside of unions, but as the > following testcase shows, not everything has been adjusted for that. > Unlike structures, in unions flexible array member (as an extension) > can be any of the members, not just the last one, as in union all > members are effectively last. > The first hunk is about an ICE on the initialization of the FAM > in union which is not the last FIELD_DECL with a string literal, > the second hunk just formatting fix, third hunk fixes a bug in which > we were just throwing away the initializers (except for with string literal) > of FAMs in unions which aren't the last FIELD_DECL, and the last hunk > is to diagnose FAM errors in unions the same as for structures, in > particular trying to initialize a FAM with non-constant or initialization > in nested context. > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? > > 2025-02-26 Jakub Jelinek <ja...@redhat.com> > > PR c/119001 > gcc/ > * varasm.cc (output_constructor_regular_field): Don't fail > assertion if next is non-NULL and FIELD_DECL if > TREE_CODE (local->type) is UNION_TYPE. > gcc/c/ > * c-typeck.cc (pop_init_level): Don't clear constructor_type > if DECL_CHAIN of constructor_fields is NULL but p->type is UNION_TYPE. > Formatting fix. > (process_init_element): Diagnose non-static initialization of flexible > array member in union or FAM in union initialization in nested context. > gcc/testsuite/ > * gcc.dg/pr119001-1.c: New test. > * gcc.dg/pr119001-2.c: New test. > > --- 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/c/c-typeck.cc.jj 2025-02-13 14:10:52.934623189 +0100 > +++ gcc/c/c-typeck.cc 2025-02-25 11:54:39.857363690 +0100 > @@ -10270,7 +10270,8 @@ pop_init_level (location_t loc, int impl > gcc_assert (!TYPE_SIZE (constructor_type)); > > if (constructor_depth > 2) > - error_init (loc, "initialization of flexible array member in a nested > context"); > + error_init (loc, "initialization of flexible array member " > + "in a nested context"); > else > pedwarn_init (loc, OPT_Wpedantic, > "initialization of a flexible array member"); > @@ -10278,7 +10279,8 @@ pop_init_level (location_t loc, int impl > /* We have already issued an error message for the existence > of a flexible array member not at the end of the structure. > Discard the initializer so that we do not die later. */ > - if (DECL_CHAIN (constructor_fields) != NULL_TREE) > + if (DECL_CHAIN (constructor_fields) != NULL_TREE > + && (!p->type || TREE_CODE (p->type) != UNION_TYPE)) > constructor_type = NULL_TREE; > } > } > @@ -12124,6 +12126,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/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:48:32.058509052 +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 V y = { .a = "abcdefghijk" }; > +union V 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:31:21.449928528 +0100 > @@ -0,0 +1,20 @@ > +/* 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" } */ > + > +void > +foo (int x) > +{ > + union U a = { { x, x + 1 } }; /* { dg-error "non-static initialization of > a flexible array member" } */ > + union U b = { .a = { x + 2, x + 3 } }; /* { dg-error "non-static > initialization of a flexible array member" } */ > + union V c = { .a = { x + 4, x + 5 } }; /* { dg-error "non-static > initialization of a flexible array member" } */ > +} > > Jakub >