From: Martin Uecker <uecker@tugraz.at>
To: gcc-patches@gcc.gnu.org
Cc: Joseph Myers <joseph@codesourcery.com>
Subject: [PATCH 4/4] c23: construct composite type for tagged types
Date: Thu, 16 Nov 2023 22:40:09 +0100 [thread overview]
Message-ID: <e926b4d4153c5feb41a22ba10f54f571bc38a19b.camel@tugraz.at> (raw)
In-Reply-To: <02a9b94e4d653b6f1b9f89a1b62187f46e871738.camel@tugraz.at>
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 262b04c582f..2255fb66bb2 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -381,8 +381,15 @@ build_functype_attribute_variant (tree ntype, tree otype, tree attrs)
nonzero; if that isn't so, this may crash. In particular, we
assume that qualifiers match. */
+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 = TREE_TYPE (t1);
tree pointed_to_2 = TREE_TYPE (t2);
- tree target = composite_type (pointed_to_1, pointed_to_2);
+ tree target = composite_type_internal (pointed_to_1,
+ pointed_to_2, cache);
t1 = build_pointer_type_for_mode (target, TYPE_MODE (t1), false);
t1 = build_type_attribute_variant (t1, attributes);
return qualify_type (t1, t2);
@@ -435,7 +443,8 @@ composite_type (tree t1, tree t2)
case ARRAY_TYPE:
{
- tree elt = composite_type (TREE_TYPE (t1), TREE_TYPE (t2));
+ tree elt = composite_type_internal (TREE_TYPE (t1), TREE_TYPE (t2),
+ cache);
int quals;
tree unqual_elt;
tree d1 = TYPE_DOMAIN (t1);
@@ -503,9 +512,61 @@ composite_type (tree t1, tree t2)
return build_type_attribute_variant (t1, attributes);
}
- 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 = cache; c != NULL; c = c->next)
+ if (c->t1 == t1 && c->t2 == t2)
+ return c->composite;
+
+ /* Otherwise, create a new type node and link it into the cache. */
+
+ tree n = make_node (code1);
+ struct composite_cache cache2 = { t1, t2, n, cache };
+ cache = &cache2;
+
+ tree f1 = TYPE_FIELDS (t1);
+ tree f2 = TYPE_FIELDS (t2);
+ tree fields = NULL_TREE;
+
+ for (tree a = f1, b = f2; a && b;
+ a = DECL_CHAIN (a), b = DECL_CHAIN (b))
+ {
+ tree ta = TREE_TYPE (a);
+ tree tb = TREE_TYPE (b);
+
+ gcc_assert (DECL_NAME (a) == DECL_NAME (b));
+ gcc_assert (comptypes (ta, tb));
+
+ tree f = build_decl (input_location, FIELD_DECL, DECL_NAME (a),
+ composite_type_internal (ta, tb, cache));
+
+ DECL_FIELD_CONTEXT (f) = n;
+ DECL_CHAIN (f) = fields;
+ fields = f;
+ }
+
+ TYPE_NAME (n) = TYPE_NAME (t1);
+ TYPE_FIELDS (n) = nreverse (fields);
+ TYPE_ATTRIBUTES (n) = attributes;
+ layout_type (n);
+ n = build_type_attribute_variant (n, attributes);
+ n = qualify_type (n, t1);
+
+ gcc_checking_assert (comptypes (n, t1));
+ gcc_checking_assert (comptypes (n, t2));
+
+ return n;
+ }
+ /* FALLTHRU */
+ case ENUMERAL_TYPE:
if (attributes != 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 = composite_type (TREE_TYPE (t1), TREE_TYPE (t2));
+ tree valtype = composite_type_internal (TREE_TYPE (t1),
+ TREE_TYPE (t2), cache);
tree p1 = TYPE_ARG_TYPES (t1);
tree p2 = TYPE_ARG_TYPES (t2);
int len;
@@ -565,6 +627,16 @@ composite_type (tree t1, tree t2)
for (; p1 && p1 != void_list_node;
p1 = TREE_CHAIN (p1), p2 = TREE_CHAIN (p2), n = TREE_CHAIN (n))
{
+ tree mv1 = TREE_VALUE (p1);
+ if (mv1 && mv1 != error_mark_node
+ && TREE_CODE (mv1) != ARRAY_TYPE)
+ mv1 = TYPE_MAIN_VARIANT (mv1);
+
+ tree mv2 = TREE_VALUE (p2);
+ if (mv2 && mv2 != error_mark_node
+ && TREE_CODE (mv2) != ARRAY_TYPE)
+ mv2 = TYPE_MAIN_VARIANT (mv2);
+
/* A null type means arg type is not specified.
Take whatever the other function type has. */
if (TREE_VALUE (p1) == NULL_TREE)
@@ -585,10 +657,6 @@ composite_type (tree t1, tree t2)
&& TREE_VALUE (p1) != TREE_VALUE (p2))
{
tree memb;
- tree mv2 = TREE_VALUE (p2);
- if (mv2 && mv2 != error_mark_node
- && TREE_CODE (mv2) != ARRAY_TYPE)
- mv2 = TYPE_MAIN_VARIANT (mv2);
for (memb = TYPE_FIELDS (TREE_VALUE (p1));
memb; memb = DECL_CHAIN (memb))
{
@@ -598,8 +666,9 @@ composite_type (tree t1, tree t2)
mv3 = TYPE_MAIN_VARIANT (mv3);
if (comptypes (mv3, mv2))
{
- TREE_VALUE (n) = composite_type (TREE_TYPE (memb),
- TREE_VALUE (p2));
+ TREE_VALUE (n) = 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) != TREE_VALUE (p1))
{
tree memb;
- tree mv1 = TREE_VALUE (p1);
- if (mv1 && mv1 != error_mark_node
- && TREE_CODE (mv1) != ARRAY_TYPE)
- mv1 = TYPE_MAIN_VARIANT (mv1);
for (memb = TYPE_FIELDS (TREE_VALUE (p2));
memb; memb = DECL_CHAIN (memb))
{
@@ -623,15 +688,17 @@ composite_type (tree t1, tree t2)
mv3 = TYPE_MAIN_VARIANT (mv3);
if (comptypes (mv3, mv1))
{
- TREE_VALUE (n) = composite_type (TREE_TYPE (memb),
- TREE_VALUE (p1));
+ TREE_VALUE (n)
+ = 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) = composite_type (TREE_VALUE (p1), TREE_VALUE (p2));
+ TREE_VALUE (n) = composite_type_internal (mv1, mv2, cache);
parm_done: ;
}
@@ -643,7 +710,13 @@ composite_type (tree t1, tree t2)
default:
return build_type_attribute_variant (t1, attributes);
}
+}
+tree
+composite_type (tree t1, tree t2)
+{
+ struct composite_cache cache = { };
+ return composite_type_internal (t1, t2, &cache);
}
/* Return the type of a conditional expression between pointers to
@@ -5528,6 +5601,11 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
result_type = type2;
else if (code1 == POINTER_TYPE && code2 == NULLPTR_TYPE)
result_type = 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 = composite_type (TYPE_MAIN_VARIANT (type1),
+ TYPE_MAIN_VARIANT (type2));
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=c23" } */
+
+void b(void)
+{
+ int n = 3;
+
+ extern struct f { char (*x)[3]; char (*y)[]; } q;
+ { extern struct f { char (*x)[]; char (*y)[4]; } q;
+ _Static_assert(3 == sizeof(*q.x), "");
+ _Static_assert(4 == sizeof(*q.y), "");
+ }
+ { extern struct f { char (*x)[2]; char (*y)[]; } q; (void)q; } /* { dg-error "conflicting" } */
+
+ { struct f { char (*x)[n]; char (*y)[3]; }* qp = &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=c23" } */
+
+
+struct foo { int (*(*i)(void))[]; } x;
+
+
+void f(void)
+{
+ const struct foo { int (*(*i)())[3]; } y;
+ _Static_assert(3 * sizeof(int) == 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=c23" }
+ */
+
+// 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=c23" }
+ */
+
+// 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;
+}
+
--
2.39.2
next prev parent reply other threads:[~2023-11-16 21:40 UTC|newest]
Thread overview: 67+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-11-16 21:36 c23 type compatibility rules, v3 Martin Uecker
2023-11-16 21:38 ` [PATCH 1/4] c23: tag compatibility rules for struct and unions Martin Uecker
2023-11-23 23:17 ` Joseph Myers
2023-11-16 21:38 ` [PATCH 2/4] c23: tag compatibility rules for enums Martin Uecker
2023-11-23 23:26 ` Joseph Myers
2023-11-16 21:39 ` [PATCH 3/4] c23: aliasing of compatible tagged types Martin Uecker
2023-11-23 23:47 ` Joseph Myers
2023-11-26 22:48 ` Martin Uecker
2023-11-27 7:46 ` Richard Biener
2023-11-28 1:00 ` Joseph Myers
2023-11-28 6:49 ` Martin Uecker
2023-11-28 10:47 ` Richard Biener
2023-11-28 11:51 ` Martin Uecker
2023-11-16 21:40 ` Martin Uecker [this message]
2023-11-27 13:16 ` [V4] [C PATCH 1/4] c23: tag compatibility rules for struct and unions Martin Uecker
2023-12-14 20:53 ` Joseph Myers
2023-11-27 13:16 ` [V4] [PATCH 2/4] c23: tag compatibility rules for enums Martin Uecker
2023-12-14 20:58 ` Joseph Myers
2023-11-27 13:16 ` [V4] [PATCH 3/4] c23: aliasing of compatible tagged types Martin Uecker
2023-12-14 21:10 ` Joseph Myers
2023-11-27 13:16 ` [V4] [PATCH 4/4] c23: construct composite type for " Martin Uecker
2023-12-17 17:41 ` [V5] [C PATCH 1/4] c23: tag compatibility rules for struct and unions Martin Uecker
2023-12-19 21:48 ` Joseph Myers
2023-12-17 17:42 ` [V5] [C PATCH 2/4] c23: tag compatibility rules for enums Martin Uecker
2023-12-19 21:50 ` Joseph Myers
2023-12-17 17:42 ` [V5] [C PATCH 3/4] c23: aliasing of compatible tagged types Martin Uecker
2023-12-19 22:02 ` Joseph Myers
2023-12-17 17:42 ` [V5] [C PATCH 4/4] c23: construct composite type for " Martin Uecker
2023-12-19 22:25 ` Joseph Myers
2023-12-21 21:47 ` [V6] " Martin Uecker
2023-12-22 16:27 ` Joseph Myers
2023-12-27 19:23 ` [C PATCH] C: Fix type compatibility for structs with variable sized fields Martin Uecker
2023-12-29 15:57 ` Joseph Myers
2024-01-27 16:10 ` Fix ICE with -g and -std=c23 when forming composite types [PR113438] Martin Uecker
2024-01-29 20:27 ` Joseph Myers
2024-04-02 18:54 ` [C PATCH] Fix ICE with -g and -std=c23 related to incomplete types [PR114361] Martin Uecker
2024-04-02 20:31 ` Joseph Myers
2024-04-02 19:02 ` [C PATCH] fix aliasing for structures/unions with incomplete types Martin Uecker
2024-04-02 20:42 ` Joseph Myers
2024-04-02 21:22 ` Martin Uecker
2024-04-03 15:33 ` Joseph Myers
2024-04-14 12:30 ` [C PATCH, v2] Fix ICE with -g and -std=c23 related to incomplete types [PR114361] Martin Uecker
2024-04-14 12:38 ` Martin Uecker
2024-04-15 6:55 ` Richard Biener
2024-04-15 7:38 ` Jakub Jelinek
2024-04-15 7:59 ` Jakub Jelinek
2024-04-15 8:02 ` Richard Biener
2024-04-15 8:05 ` Jakub Jelinek
2024-04-15 10:48 ` [PATCH] c, v3: " Jakub Jelinek
2024-04-15 11:33 ` Richard Biener
2024-04-16 7:20 ` Jakub Jelinek
2024-04-19 20:39 ` Joseph Myers
2024-04-15 7:03 ` [C PATCH, v2] " Jakub Jelinek
2024-05-18 13:27 ` [C PATCH] Fix for some variably modified types not being recognized [PR114831] Martin Uecker
2024-05-18 13:29 ` Martin Uecker
2024-05-20 21:18 ` Joseph Myers
2024-05-18 20:18 ` [C PATCH] Fix for redeclared enumerator initialized with different type [PR115109] Martin Uecker
2024-05-19 10:24 ` [C PATCH, v2] " Martin Uecker
2024-05-20 21:30 ` Joseph Myers
2024-05-21 5:40 ` Martin Uecker
2024-05-23 20:51 ` Joseph Myers
2024-05-21 12:18 ` [C PATCH]: allow aliasing of compatible types derived from enumeral types [PR115157] Martin Uecker
2024-05-23 20:59 ` Joseph Myers
2024-05-23 21:30 ` Ian Lance Taylor
2024-05-23 21:47 ` Martin Uecker
2024-05-23 21:53 ` Ian Lance Taylor
2024-05-24 5:56 ` Richard Biener
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=e926b4d4153c5feb41a22ba10f54f571bc38a19b.camel@tugraz.at \
--to=uecker@tugraz.at \
--cc=gcc-patches@gcc.gnu.org \
--cc=joseph@codesourcery.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).