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/c2x-tag-composite-1.c: New test.
* gcc.dg/c2x-tag-composite-2.c: New test.
* gcc.dg/c2x-tag-composite-3.c: New test.
* gcc.dg/c2x-tag-composite-4.c: New test.
---
gcc/c/c-typeck.cc | 114 +
gcc/testsuite/gcc.dg/c2x-tag-composite-1.c | 26 +
gcc/testsuite/gcc.dg/c2x-tag-composite-2.c | 16 +++
gcc/testsuite/gcc.dg/c2x-tag-composite-3.c | 17 +++
gcc/testsuite/gcc.dg/c2x-tag-composite-4.c | 21
5 files changed, 176 insertions(+), 18 deletions(-)
create mode 100644 gcc/testsuite/gcc.dg/c2x-tag-composite-1.c
create mode 100644 gcc/testsuite/gcc.dg/c2x-tag-composite-2.c
create mode 100644 gcc/testsuite/gcc.dg/c2x-tag-composite-3.c
create mode 100644 gcc/testsuite/gcc.dg/c2x-tag-composite-4.c
diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index 2489fa1e3d1..357367eab09 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;
@@ -425,7 +432,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);
@@ -433,7 +441,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);
@@ -501,9 +510,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_isoc2x && !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 =
+
+ 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. */
@@ -518,7 +579,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