modify the shared type, so we gcc_assert (itype)
below. */
{
+ /* Identify typeless storage as introduced in C2Y
+ and supported also in earlier language modes. */
+ bool typeless = (char_type_p (type)
+ && !(type_quals & TYPE_QUAL_ATOMIC))
+ || (AGGREGATE_TYPE_P (type)
+ && TYPE_TYPELESS_STORAGE (type));
+
addr_space_t as = DECODE_QUAL_ADDR_SPACE (type_quals);
if (!ADDR_SPACE_GENERIC_P (as) && as != TYPE_ADDR_SPACE (type))
type = build_qualified_type (type,
ENCODE_QUAL_ADDR_SPACE (as));
-
- type = build_array_type (type, itype);
+ type = build_array_type (type, itype, typeless);
}
if (type != error_mark_node)
if (DECL_NAME (x)
|| RECORD_OR_UNION_TYPE_P (TREE_TYPE (x)))
saw_named_field = true;
+
+ if (AGGREGATE_TYPE_P (TREE_TYPE (x))
+ && TYPE_TYPELESS_STORAGE (TREE_TYPE (x)))
+ TYPE_TYPELESS_STORAGE (t) = true;
}
detect_field_duplicates (fieldlist);
TYPE_FIELDS (x) = TYPE_FIELDS (t);
TYPE_LANG_SPECIFIC (x) = TYPE_LANG_SPECIFIC (t);
TYPE_TRANSPARENT_AGGR (x) = TYPE_TRANSPARENT_AGGR (t);
+ TYPE_TYPELESS_STORAGE (x) = TYPE_TYPELESS_STORAGE (t);
C_TYPE_FIELDS_READONLY (x) = C_TYPE_FIELDS_READONLY (t);
C_TYPE_FIELDS_VOLATILE (x) = C_TYPE_FIELDS_VOLATILE (t);
C_TYPE_FIELDS_NON_CONSTEXPR (x) = C_TYPE_FIELDS_NON_CONSTEXPR (t);
--- /dev/null
+/* { dg-do run } */
+/* { dg-options "-std=c2y -O2" } */
+
+struct f { _Alignas(int) char buf[sizeof(int)]; };
+struct f2 { struct f x; };
+union g { _Alignas(int) char buf[sizeof(int)]; };
+
+[[gnu::noinline]]
+int foo(struct f *p, int *q)
+{
+ *q = 1;
+ *p = (struct f){ };
+ return *q;
+}
+
+[[gnu::noinline]]
+int foo2(struct f2 *p, int *q)
+{
+ *q = 1;
+ *p = (struct f2){ };
+ return *q;
+}
+
+[[gnu::noinline]]
+int bar(union g *p, int *q)
+{
+ *q = 1;
+ *p = (union g){ };
+ return *q;
+}
+
+
+int main()
+{
+ struct f p;
+ if (0 != foo(&p, (void*)&p.buf))
+ __builtin_abort();
+
+ struct f2 p2;
+ if (0 != foo2(&p2, (void*)&p2.x.buf))
+ __builtin_abort();
+
+ union g q;
+ if (0 != bar(&q, (void*)&q.buf))
+ __builtin_abort();
+}
--- /dev/null
+/* { dg-do run } */
+/* { dg-options "-std=c2y -O2" } */
+
+struct f2 {
+ struct f {
+ _Alignas(int) char buf[sizeof(int)];
+ } x[2];
+ int i;
+};
+
+[[gnu::noinline]]
+int foo2(struct f2 *p, int *q)
+{
+ *q = 1;
+ *p = (struct f2){ };
+ return *q;
+}
+
+struct g2 {
+ union g {
+ _Alignas(int) char buf[sizeof(int)];
+ } x[2];
+ int i;
+};
+
+[[gnu::noinline]]
+int bar2(struct g2 *p, int *q)
+{
+ *q = 1;
+ *p = (struct g2){ };
+ return *q;
+}
+
+int main()
+{
+ struct f2 p2;
+ if (0 != foo2(&p2, (void*)&p2.x[0].buf))
+ __builtin_abort();
+
+ struct g2 q2;
+ if (0 != bar2(&q2, (void*)&q2.x[0].buf))
+ __builtin_abort();
+}
--- /dev/null
+/* { dg-do run } */
+/* { dg-options "-std=c2y -O2" } */
+
+struct f { _Alignas(int) typeof(volatile char) buf[sizeof(int)]; };
+struct f2 { struct f x; };
+union g { _Alignas(int) volatile char buf[sizeof(int)]; };
+
+
+[[gnu::noinline]]
+int foo(struct f *p, int *q)
+{
+ *q = 1;
+ *p = (struct f){ };
+ return *q;
+}
+
+[[gnu::noinline]]
+int foo2(struct f2 *p, int *q)
+{
+ *q = 1;
+ *p = (struct f2){ };
+ return *q;
+}
+
+[[gnu::noinline]]
+int bar(union g *p, int *q)
+{
+ *q = 1;
+ *p = (union g){ };
+ return *q;
+}
+
+
+int main()
+{
+ struct f p;
+ if (0 != foo(&p, (void*)&p.buf))
+ __builtin_abort();
+
+ struct f2 p2;
+ if (0 != foo2(&p2, (void*)&p2.x.buf))
+ __builtin_abort();
+
+ union g q;
+ if (0 != bar(&q, (void*)&q.buf))
+ __builtin_abort();
+}