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");
/* 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;
}
}
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
--- /dev/null
+/* 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 ();
+}
--- /dev/null
+/* 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" } */
+}
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));