From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mailrelay.tugraz.at (mailrelay.tugraz.at [129.27.2.202]) by sourceware.org (Postfix) with ESMTPS id 22B22385829E for ; Mon, 27 Nov 2023 13:16:51 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 22B22385829E Authentication-Results: sourceware.org; dmarc=pass (p=quarantine dis=none) header.from=tugraz.at Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=tugraz.at ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 22B22385829E Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=129.27.2.202 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701091014; cv=none; b=F4h4kYrwcc8TBTmb1uUTHeO/8GZRVLHV19zRwUwEy95eLRqq76B1QuPoUQA2nC8XiD7OmelaW+MM9saUa/sswUIkjNGIW9RhnJAsGcoG5RHmlZAENldTeR9QNdvt200w0Op461QGtHQ9xD/aBhPHOI1uBJxHnviRkoZD8GJCDug= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701091014; c=relaxed/simple; bh=5wxiZ9qdGxsG3aA1csz27SuHxOmUC0QsCbMHIctg9zw=; h=DKIM-Signature:Message-ID:Subject:From:To:Date:MIME-Version; b=EnQ4ER/HirPBaONj/9n6llp09WgaGDkbAdLqIicdHQ3np89EhnvGnlIvSr1zN8lWk9EBV+uILTqTlCB4RTt/fn4Es8WcI1nAKLtvRZD8zQ6ZMee2WZeB1RPRnrmwiDanH1zPdF7R2E4rbUq9p+Hf+LRiLWHsYdrDTMCrMa5Vhp0= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from fbmtpc21.tugraz.at (fbmtpc21.tugraz.at [129.27.144.40]) by mailrelay.tugraz.at (Postfix) with ESMTPSA id 4Sf5hd0QBgz1LM09; Mon, 27 Nov 2023 14:16:49 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 mailrelay.tugraz.at 4Sf5hd0QBgz1LM09 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=tugraz.at; s=mailrelay; t=1701091009; bh=K5+V8J4kA1YYxxus9w3R0Xam2rkfmYzCd2FWA/IB5lc=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=qIYCV7PhrNkS40A2m876D5niCwN1AGZul/0CC63ue7J/hUbvqeHmFzDPLUDk99keI qFq4do4PdzDmjcuCGzdAtmc4vm9QfIuDDoDHuXD0EcHnOds12l8XpnfnrKqfH8UW40 vm7A9OqzpjjBHvoYoi2pxkTiMqmXFnyRwyefs9hg= Message-ID: Subject: [V4] [PATCH 4/4] c23: construct composite type for tagged types From: Martin Uecker To: gcc-patches@gcc.gnu.org Cc: Joseph Myers Date: Mon, 27 Nov 2023 14:16:48 +0100 In-Reply-To: <02a9b94e4d653b6f1b9f89a1b62187f46e871738.camel@tugraz.at> References: <02a9b94e4d653b6f1b9f89a1b62187f46e871738.camel@tugraz.at> Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable User-Agent: Evolution 3.46.4-2 MIME-Version: 1.0 X-TUG-Backscatter-control: G/VXY7/6zeyuAY/PU2/0qw X-Spam-Scanner: SpamAssassin 3.003001 X-Spam-Score-relay: -1.9 X-Scanned-By: MIMEDefang 2.74 on 129.27.10.116 X-Spam-Status: No, score=-10.7 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE,SPF_PASS,TXREP,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: (this patch was still not updated and needs more work, so only included now for completeness)=20 c23: construct composite type for tagged types Support for constructing composite type for structs and unions in C23. gcc/c: * c-typeck.cc (composite_type_internal): Adapted from composite_type to support structs and unions. (composite_type): New wrapper function. (build_conditional_operator): Return composite type. gcc/testsuite: * gcc.dg/c23-tag-composite-1.c: New test. * gcc.dg/c23-tag-composite-2.c: New test. * gcc.dg/c23-tag-composite-3.c: New test. * gcc.dg/c23-tag-composite-4.c: New test. --- gcc/c/c-typeck.cc | 114 +++++++++++++++++---- gcc/testsuite/gcc.dg/c23-tag-composite-1.c | 26 +++++ gcc/testsuite/gcc.dg/c23-tag-composite-2.c | 16 +++ gcc/testsuite/gcc.dg/c23-tag-composite-3.c | 17 +++ gcc/testsuite/gcc.dg/c23-tag-composite-4.c | 21 ++++ 5 files changed, 176 insertions(+), 18 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/c23-tag-composite-1.c create mode 100644 gcc/testsuite/gcc.dg/c23-tag-composite-2.c create mode 100644 gcc/testsuite/gcc.dg/c23-tag-composite-3.c create mode 100644 gcc/testsuite/gcc.dg/c23-tag-composite-4.c diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc index 00eb65dbcce..7901368c9fd 100644 --- a/gcc/c/c-typeck.cc +++ b/gcc/c/c-typeck.cc @@ -381,8 +381,15 @@ build_functype_attribute_variant (tree ntype, tree oty= pe, tree attrs) nonzero; if that isn't so, this may crash. In particular, we assume that qualifiers match. */ =20 +struct composite_cache { + tree t1; + tree t2; + tree composite; + struct composite_cache* next; +}; + tree -composite_type (tree t1, tree t2) +composite_type_internal (tree t1, tree t2, struct composite_cache* cache) { enum tree_code code1; enum tree_code code2; @@ -427,7 +434,8 @@ composite_type (tree t1, tree t2) { tree pointed_to_1 =3D TREE_TYPE (t1); tree pointed_to_2 =3D TREE_TYPE (t2); - tree target =3D composite_type (pointed_to_1, pointed_to_2); + tree target =3D composite_type_internal (pointed_to_1, + pointed_to_2, cache); t1 =3D build_pointer_type_for_mode (target, TYPE_MODE (t1), false)= ; t1 =3D build_type_attribute_variant (t1, attributes); return qualify_type (t1, t2); @@ -435,7 +443,8 @@ composite_type (tree t1, tree t2) =20 case ARRAY_TYPE: { - tree elt =3D composite_type (TREE_TYPE (t1), TREE_TYPE (t2)); + tree elt =3D composite_type_internal (TREE_TYPE (t1), TREE_TYPE (t2), + cache); int quals; tree unqual_elt; tree d1 =3D TYPE_DOMAIN (t1); @@ -503,9 +512,61 @@ composite_type (tree t1, tree t2) return build_type_attribute_variant (t1, attributes); } =20 - case ENUMERAL_TYPE: case RECORD_TYPE: case UNION_TYPE: + if (flag_isoc23 && !comptypes_same_p (t1, t2)) + { + gcc_checking_assert (COMPLETE_TYPE_P (t1) && COMPLETE_TYPE_P (t2)); + gcc_checking_assert (comptypes (t1, t2)); + + /* If a composite type for these two types is already under + construction, return it. */ + + for (struct composite_cache *c =3D cache; c !=3D NULL; c =3D c->next) + if (c->t1 =3D=3D t1 && c->t2 =3D=3D t2) + return c->composite; + + /* Otherwise, create a new type node and link it into the cache. */ + + tree n =3D make_node (code1); + struct composite_cache cache2 =3D { t1, t2, n, cache }; + cache =3D &cache2; + + tree f1 =3D TYPE_FIELDS (t1); + tree f2 =3D TYPE_FIELDS (t2); + tree fields =3D NULL_TREE; + + for (tree a =3D f1, b =3D f2; a && b; + a =3D DECL_CHAIN (a), b =3D DECL_CHAIN (b)) + { + tree ta =3D TREE_TYPE (a); + tree tb =3D TREE_TYPE (b); + + gcc_assert (DECL_NAME (a) =3D=3D DECL_NAME (b)); + gcc_assert (comptypes (ta, tb)); + + tree f =3D build_decl (input_location, FIELD_DECL, DECL_NAME (a), + composite_type_internal (ta, tb, cache)); + + DECL_FIELD_CONTEXT (f) =3D n; + DECL_CHAIN (f) =3D fields; + fields =3D f; + } + + TYPE_NAME (n) =3D TYPE_NAME (t1); + TYPE_FIELDS (n) =3D nreverse (fields); + TYPE_ATTRIBUTES (n) =3D attributes; + layout_type (n); + n =3D build_type_attribute_variant (n, attributes); + n =3D qualify_type (n, t1); + + gcc_checking_assert (comptypes (n, t1)); + gcc_checking_assert (comptypes (n, t2)); + + return n; + } + /* FALLTHRU */ + case ENUMERAL_TYPE: if (attributes !=3D NULL) { /* Try harder not to create a new aggregate type. */ @@ -520,7 +581,8 @@ composite_type (tree t1, tree t2) /* Function types: prefer the one that specified arg types. If both do, merge the arg types. Also merge the return types. */ { - tree valtype =3D composite_type (TREE_TYPE (t1), TREE_TYPE (t2)); + tree valtype =3D composite_type_internal (TREE_TYPE (t1), + TREE_TYPE (t2), cache); tree p1 =3D TYPE_ARG_TYPES (t1); tree p2 =3D TYPE_ARG_TYPES (t2); int len; @@ -565,6 +627,16 @@ composite_type (tree t1, tree t2) for (; p1 && p1 !=3D void_list_node; p1 =3D TREE_CHAIN (p1), p2 =3D TREE_CHAIN (p2), n =3D TREE_CHAIN (n)= ) { + tree mv1 =3D TREE_VALUE (p1); + if (mv1 && mv1 !=3D error_mark_node + && TREE_CODE (mv1) !=3D ARRAY_TYPE) + mv1 =3D TYPE_MAIN_VARIANT (mv1); + + tree mv2 =3D TREE_VALUE (p2); + if (mv2 && mv2 !=3D error_mark_node + && TREE_CODE (mv2) !=3D ARRAY_TYPE) + mv2 =3D TYPE_MAIN_VARIANT (mv2); + /* A null type means arg type is not specified. Take whatever the other function type has. */ if (TREE_VALUE (p1) =3D=3D NULL_TREE) @@ -585,10 +657,6 @@ composite_type (tree t1, tree t2) && TREE_VALUE (p1) !=3D TREE_VALUE (p2)) { tree memb; - tree mv2 =3D TREE_VALUE (p2); - if (mv2 && mv2 !=3D error_mark_node - && TREE_CODE (mv2) !=3D ARRAY_TYPE) - mv2 =3D TYPE_MAIN_VARIANT (mv2); for (memb =3D TYPE_FIELDS (TREE_VALUE (p1)); memb; memb =3D DECL_CHAIN (memb)) { @@ -598,8 +666,9 @@ composite_type (tree t1, tree t2) mv3 =3D TYPE_MAIN_VARIANT (mv3); if (comptypes (mv3, mv2)) { - TREE_VALUE (n) =3D composite_type (TREE_TYPE (memb), - TREE_VALUE (p2)); + TREE_VALUE (n) =3D composite_type_internal (TREE_TYPE (memb), + TREE_VALUE (p2), + cache); pedwarn (input_location, OPT_Wpedantic, "function types not truly compatible in ISO C"); goto parm_done; @@ -610,10 +679,6 @@ composite_type (tree t1, tree t2) && TREE_VALUE (p2) !=3D TREE_VALUE (p1)) { tree memb; - tree mv1 =3D TREE_VALUE (p1); - if (mv1 && mv1 !=3D error_mark_node - && TREE_CODE (mv1) !=3D ARRAY_TYPE) - mv1 =3D TYPE_MAIN_VARIANT (mv1); for (memb =3D TYPE_FIELDS (TREE_VALUE (p2)); memb; memb =3D DECL_CHAIN (memb)) { @@ -623,15 +688,17 @@ composite_type (tree t1, tree t2) mv3 =3D TYPE_MAIN_VARIANT (mv3); if (comptypes (mv3, mv1)) { - TREE_VALUE (n) =3D composite_type (TREE_TYPE (memb), - TREE_VALUE (p1)); + TREE_VALUE (n) + =3D composite_type_internal (TREE_TYPE (memb), + TREE_VALUE (p1), + cache); pedwarn (input_location, OPT_Wpedantic, "function types not truly compatible in ISO C"); goto parm_done; } } } - TREE_VALUE (n) =3D composite_type (TREE_VALUE (p1), TREE_VALUE (p2)); + TREE_VALUE (n) =3D composite_type_internal (mv1, mv2, cache); parm_done: ; } =20 @@ -643,7 +710,13 @@ composite_type (tree t1, tree t2) default: return build_type_attribute_variant (t1, attributes); } +} =20 +tree +composite_type (tree t1, tree t2) +{ + struct composite_cache cache =3D { }; + return composite_type_internal (t1, t2, &cache); } =20 /* Return the type of a conditional expression between pointers to @@ -5528,6 +5601,11 @@ build_conditional_expr (location_t colon_loc, tree i= fexp, bool ifexp_bcp, result_type =3D type2; else if (code1 =3D=3D POINTER_TYPE && code2 =3D=3D NULLPTR_TYPE) result_type =3D type1; + else if (RECORD_OR_UNION_TYPE_P (type1) && RECORD_OR_UNION_TYPE_P (type2= ) + && comptypes (TYPE_MAIN_VARIANT (type1), + TYPE_MAIN_VARIANT (type2))) + result_type =3D composite_type (TYPE_MAIN_VARIANT (type1), + TYPE_MAIN_VARIANT (type2)); =20 if (!result_type) { diff --git a/gcc/testsuite/gcc.dg/c23-tag-composite-1.c b/gcc/testsuite/gcc= .dg/c23-tag-composite-1.c new file mode 100644 index 00000000000..d79c8eefc91 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c23-tag-composite-1.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-options "-std=3Dc23" } */ + +void b(void) +{ + int n =3D 3; + + extern struct f { char (*x)[3]; char (*y)[]; } q; + { extern struct f { char (*x)[]; char (*y)[4]; } q;=20 + _Static_assert(3 =3D=3D sizeof(*q.x), ""); + _Static_assert(4 =3D=3D sizeof(*q.y), ""); + } + { extern struct f { char (*x)[2]; char (*y)[]; } q; (void)q; } /* { dg-er= ror "conflicting" } */ + + { struct f { char (*x)[n]; char (*y)[3]; }* qp =3D &q; (void)*qp; } + (void)q; + + static struct g { int a; char buf[n]; } *p; (void)p; + { static struct g { int a; char buf[3]; } *p; (void)p; } + + static struct h { int a; void (*s)(char buf[n]); } *t; (void)t; + { static struct h { int a; void (*s)(char buf[3]); } *t; (void)t; } +} + + + diff --git a/gcc/testsuite/gcc.dg/c23-tag-composite-2.c b/gcc/testsuite/gcc= .dg/c23-tag-composite-2.c new file mode 100644 index 00000000000..0b06c573e87 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c23-tag-composite-2.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-std=3Dc23" } */ + + +struct foo { int (*(*i)(void))[]; } x; + + +void f(void) +{=20 + const struct foo { int (*(*i)())[3]; } y; + _Static_assert(3 * sizeof(int) =3D=3D sizeof(*((1 ? &x : &y)->i())), ""); +} + +void g(struct foo { int x; } a); +void g(const struct foo { int x; } a); + diff --git a/gcc/testsuite/gcc.dg/c23-tag-composite-3.c b/gcc/testsuite/gcc= .dg/c23-tag-composite-3.c new file mode 100644 index 00000000000..bc689478d8d --- /dev/null +++ b/gcc/testsuite/gcc.dg/c23-tag-composite-3.c @@ -0,0 +1,17 @@ +/* { dg-do compile } + * { dg-options "-std=3Dc23" } + */ + +// bit-fields + +extern struct foo { int x:3; } x; +struct foo { int x:3; } y; + +void f(void) +{ + extern typeof(*(1 ? &x : &y)) x; + &x.x; /* { dg-error "bit-field" } */ +} + +struct foo { int x:2; }; /* { dg-error "redefinition" } */ + diff --git a/gcc/testsuite/gcc.dg/c23-tag-composite-4.c b/gcc/testsuite/gcc= .dg/c23-tag-composite-4.c new file mode 100644 index 00000000000..2cc4b067c05 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c23-tag-composite-4.c @@ -0,0 +1,21 @@ +/* { dg-do compile } + * { dg-options "-std=3Dc23" }=20 + */ + +// conditional operator + +void f(void) +{ + struct foo { int x; } a; + struct foo { int x; } b; + 1 ? a : b; +} + +struct bar { int x; } a; + +void g(void) +{ + struct bar { int x; } b; + 1 ? a : b; +} + --=20 2.39.2