sub = build3 (COMPONENT_REF, inner_type, dest, field_index,
NULL_TREE);
- if (!split_nonconstant_init_1 (sub, value, true))
+ if (!split_nonconstant_init_1 (sub, value, true)
+ /* For flexible array member with initializer we
+ can't remove the initializer, because only the
+ initializer determines how many elements the
+ flexible array member has. */
+ || (!array_type_p
+ && TREE_CODE (inner_type) == ARRAY_TYPE
+ && TYPE_DOMAIN (inner_type) == NULL
+ && TREE_CODE (TREE_TYPE (value)) == ARRAY_TYPE
+ && COMPLETE_TYPE_P (TREE_TYPE (value))
+ && !integer_zerop (TYPE_SIZE (TREE_TYPE (value)))
+ && idx == CONSTRUCTOR_NELTS (init) - 1
+ && TYPE_HAS_TRIVIAL_DESTRUCTOR
+ (strip_array_types (inner_type))))
complete_p = false;
else
{
--- /dev/null
+// PR c++/88578
+// { dg-do run }
+// { dg-options -Wno-pedantic }
+
+#define STR(s) #s
+#define ASSERT(exp) \
+ ((exp) ? (void)0 : (void)(__builtin_printf ("%s:%i: assertion %s failed\n", \
+ __FILE__, __LINE__, STR(exp)), \
+ __builtin_abort ()))
+
+typedef int int32_t __attribute__((mode (__SI__)));
+
+struct Ax { int32_t n, a[]; };
+struct AAx { int32_t i; Ax ax; };
+
+int32_t i = 12345678;
+
+void
+test ()
+{
+ {
+ // OK. Does not assign any elements to flexible array.
+ Ax s = { 0 };
+ ASSERT (s.n == 0);
+ }
+ {
+ // OK only for statically allocated objects, otherwise error.
+ static Ax s = { 0, { } };
+ ASSERT (s.n == 0);
+ }
+ {
+ static Ax s = { 1, { 2 } };
+ ASSERT (s.n == 1 && s.a [0] == 2);
+ }
+ {
+ static Ax s = { 2, { 3, 4 } };
+ ASSERT (s.n = 2 && s.a [0] == 3 && s.a [1] == 4);
+ }
+ {
+ static Ax s = { 123, i };
+ ASSERT (s.n == 123 && s.a [0] == i);
+ }
+ {
+ static Ax s = { 456, { i } };
+ ASSERT (s.n == 456 && s.a [0] == i);
+ }
+ {
+ int32_t j = i + 1, k = j + 1;
+ static Ax s = { 3, { i, j, k } };
+ ASSERT (s.n == 3 && s.a [0] == i && s.a [1] == j && s.a [2] == k);
+ }
+
+ {
+ // OK. Does not assign any elements to flexible array.
+ AAx s = { 1, { 2 } };
+ ASSERT (s.i == 1 && s.ax.n == 2);
+ }
+}
+
+int
+main ()
+{
+ test ();
+ test ();
+}
--- /dev/null
+// PR c++/102295
+// { dg-do run }
+// { dg-options "" }
+
+struct A { int a; int b[]; };
+struct B { B (); int k; };
+struct C { int l; B m[]; };
+
+int x[4];
+A c = { 42, { ++x[0], ++x[1], ++x[2], ++x[3] } };
+A d = { 43, { 0, ++x[0], ++x[1], ++x[2], ++x[3] } };
+A e = { 44, { ++x[0], ++x[1], ++x[2], 17 } };
+A f = { 45 };
+C n = { 50, { B (), B () } };
+C o = { 51, {} };
+
+int
+main ()
+{
+ static A g = { 46, { ++x[0], ++x[1], ++x[2], ++x[3] } };
+ static A h = { 47, { 0, ++x[0], ++x[1], ++x[2], ++x[3] } };
+ static A i = { 48, { ++x[0], ++x[1], ++x[2], 18 } };
+ static A j = { 49 };
+ if (c.a != 42 || c.b[0] != 1 || c.b[1] != 1 || c.b[2] != 1 || c.b[3] != 1)
+ __builtin_abort ();
+ if (d.a != 43 || d.b[0] != 0 || d.b[1] != 2 || d.b[2] != 2 || d.b[3] != 2 || d.b[4] != 2)
+ __builtin_abort ();
+ if (e.a != 44 || e.b[0] != 3 || e.b[1] != 3 || e.b[2] != 3 || e.b[3] != 17)
+ __builtin_abort ();
+ if (f.a != 45)
+ __builtin_abort ();
+ if (g.a != 46 || g.b[0] != 4 || g.b[1] != 4 || g.b[2] != 4 || g.b[3] != 3)
+ __builtin_abort ();
+ if (h.a != 47 || h.b[0] != 0 || h.b[1] != 5 || h.b[2] != 5 || h.b[3] != 5 || h.b[4] != 4)
+ __builtin_abort ();
+ if (i.a != 48 || i.b[0] != 6 || i.b[1] != 6 || i.b[2] != 6 || i.b[3] != 18)
+ __builtin_abort ();
+ if (j.a != 49)
+ __builtin_abort ();
+ if (n.l != 50 || n.m[0].k != 42 || n.m[1].k != 42)
+ __builtin_abort ();
+ if (o.l != 51)
+ __builtin_abort ();
+ if (x[0] != 6 || x[1] != 6 || x[2] != 6 || x[3] != 4)
+ __builtin_abort ();
+}
+
+B::B () : k (42)
+{
+}
&& (!TYPE_DOMAIN (TREE_TYPE (local->field))
|| !TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (local->field)))))
{
- fieldsize = array_size_for_constructor (local->val);
+ unsigned HOST_WIDE_INT fldsize
+ = array_size_for_constructor (local->val);
+ fieldsize = int_size_in_bytes (TREE_TYPE (local->val));
+ /* In most cases fieldsize == fldsize as the size of the initializer
+ determines how many elements the flexible array member has. For
+ C++ fldsize can be smaller though, if the last or several last or
+ all initializers of the flexible array member have side-effects
+ 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. */
const_tree next = DECL_CHAIN (local->field);
gcc_assert (!fieldsize || !next || TREE_CODE (next) != FIELD_DECL);
- tree size = TYPE_SIZE_UNIT (TREE_TYPE (local->val));
- gcc_checking_assert (compare_tree_int (size, fieldsize) == 0);
}
else
fieldsize = tree_to_uhwi (DECL_SIZE_UNIT (local->field));