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
> 

Reply via email to