[v2] c: Add support for byte arrays in C2Y

Message ID 2aca0126cfd91f0dc0dad8529a7f5b54f8e162d2.camel@tugraz.at
State New
Headers
Series [v2] c: Add support for byte arrays in C2Y |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 fail Patch failed to apply
linaro-tcwg-bot/tcwg_gcc_build--master-arm fail Patch failed to apply

Commit Message

Martin Uecker July 13, 2024, 4:49 p.m. UTC
  -----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512


This marks structures which include a byte array
as typeless storage for all C language modes.


Bootstrapped and regression tested on x86_64.




    c: Add support for byte arrays in C2Y
    
    To get correct aliasing behavior requires that structures and unions
    that contain a byte array, i.e. an array of non-atomic character
    type (N3254), are marked with TYPE_TYPELESS_STORAGE.  This change
    affects also earlier language modes.
    
    gcc/c/
            * c-decl.cc (grokdeclarator, finish_struct): Set and
            propagate TYPE_TYPELESS_STORAGE.
    
    gcc/testsuite/
            * gcc.dg/c2y-byte-alias-1.c: New test.
            * gcc.dg/c2y-byte-alias-2.c: New test.
            * gcc.dg/c2y-byte-alias-3.c: New test.

- --- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2y-byte-alias-3.c
@@ -0,0 +1,47 @@
+/* { 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();
+}

-----BEGIN PGP SIGNATURE-----

iQIzBAEBCgAdFiEEaj/uJqwNSIjsUpyzR1yvqQNbkRUFAmaSsBkACgkQR1yvqQNb
kRWXDQ//Qy00jvmFjyjMYGBhowU5mNlweQbpK69VGUfGWqOlHk0XhJL/Ttk+pPey
Z/E3z0wXdKtbqSyJa8akk2Ek/Z4Y9ic+/b1eSOMpPu3Lc7XYrCrfx1fYly6hOlW2
sOpiurmTxKaXySuWopk1uuhGwTlD2P4jV8qjjQSiK/T7kl2RD1gDCWRsLtZob8JJ
4ucbL0rTvuQoTrbUn+qMBpTCR5IR3AnBsoxCox7oFp/s2371sl5NaljTsOfamAzb
Y0kRMr29G78HMi9sGRi0QKqU5I37mQF0MloQU1Fm6+8CYv2LNeFWG+OusLb1rUcH
FKikGWV1muCBS+0OXajkyT6SkHTf3A/3MDc9V2KCxGf6OKdF9ktPpkToqZEgWJXi
QzySfHEcZLyVpbe8CDUWeOdA721AAg9KO24rkjht2fuiyWOZSV2rKZZdSoHjVaxu
6foU9fpM6oEwZDSi02HoCXE85U04w58wo5qtsUQ0jghA0GRZZvprJNYjNUgBJPfb
S4osZET1h5JQv0vpaHzVyZH48mSOw6OqmVVGRu1N2DYj9DFhhCKT34dQYdNELU6A
WYKWWgeVyt6SGLdd0IRYThw7k0j5kSIO1I79SX9iMc3/6jfCchAJbQwejhuF2x2c
UhfR15+CmTaoK/jgbDpI7fnBk5x2bBNq27ca8YqlrEQKWRRSXaU=
=3NBa
-----END PGP SIGNATURE-----
  

Comments

Joseph Myers July 31, 2024, 8:47 p.m. UTC | #1
On Sat, 13 Jul 2024, Martin Uecker wrote:

> This marks structures which include a byte array
> as typeless storage for all C language modes.
> 
> 
> Bootstrapped and regression tested on x86_64.
> 
> 
> 
> 
>     c: Add support for byte arrays in C2Y
>     
>     To get correct aliasing behavior requires that structures and unions
>     that contain a byte array, i.e. an array of non-atomic character
>     type (N3254), are marked with TYPE_TYPELESS_STORAGE.  This change
>     affects also earlier language modes.
>     
>     gcc/c/
>             * c-decl.cc (grokdeclarator, finish_struct): Set and
>             propagate TYPE_TYPELESS_STORAGE.
>     
>     gcc/testsuite/
>             * gcc.dg/c2y-byte-alias-1.c: New test.
>             * gcc.dg/c2y-byte-alias-2.c: New test.
>             * gcc.dg/c2y-byte-alias-3.c: New test.

OK.
  

Patch

diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 97f1d346835..7b8f622296f 100644
- --- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -7502,12 +7502,18 @@  grokdeclarator (const struct c_declarator *declarator,
 	       modify the shared type, so we gcc_assert (itype)
 	       below.  */
 	      {
+		/* Identify typeless storage as introduced in C2Y
+		   and supported also in earler 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)
@@ -9659,6 +9665,10 @@  finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
       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);
@@ -9859,6 +9869,7 @@  finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
       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);
diff --git a/gcc/testsuite/gcc.dg/c2y-byte-alias-1.c b/gcc/testsuite/gcc.dg/c2y-byte-alias-1.c
new file mode 100644
index 00000000000..30bc2c09c2f
- --- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2y-byte-alias-1.c
@@ -0,0 +1,46 @@ 
+/* { 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();
+}
diff --git a/gcc/testsuite/gcc.dg/c2y-byte-alias-2.c b/gcc/testsuite/gcc.dg/c2y-byte-alias-2.c
new file mode 100644
index 00000000000..9bd2d18b386
- --- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2y-byte-alias-2.c
@@ -0,0 +1,43 @@ 
+/* { 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();
+}
diff --git a/gcc/testsuite/gcc.dg/c2y-byte-alias-3.c b/gcc/testsuite/gcc.dg/c2y-byte-alias-3.c
new file mode 100644
index 00000000000..f88eab2e92f