Implement redeclaration and compatibility rules for
structures and unions in C23.
gcc/c/:
* c-decl.cc (previous_tag): New function.
(get_parm_info): Turn off warning for C2X.
(start_struct): Allow redefinitons.
(finish_struct): Diagnose conflicts.
* c-tree.h (comptypes_same_p): Add prototype.
* c-typeck.cc (comptypes_same_p): New function
(comptypes_internal): Activate comparison of tagged
types (convert_for_assignment): Ingore qualifiers.
(digest_init): Add error.
(initialized_elementwise_p): Allow compatible types.
gcc/testsuite/:
* gcc.dg/c2x-enum-7.c: Remove warning.
* gcc.dg/c2x-tag-1.c: New test.
* gcc.dg/c2x-tag-2.c: New test.
* gcc.dg/c2x-tag-3.c: New test.
* gcc.dg/c2x-tag-4.c: New test.
* gcc.dg/c2x-tag-5.c: New test.
* gcc.dg/c2x-tag-6.c: New test.
* gcc.dg/c2x-tag-7.c: New test.
* gcc.dg/c2x-tag-8.c: New test.
* gcc.dg/c2x-tag-9.c: New test.
* gcc.dg/c2x-tag-10.c: New test.
---
gcc/c/c-decl.cc | 56 ++---
gcc/c/c-tree.h| 1 +
gcc/c/c-typeck.cc | 38 +
gcc/testsuite/gcc.dg/c2x-enum-7.c | 6 +--
gcc/testsuite/gcc.dg/c2x-tag-1.c | 68 +++
gcc/testsuite/gcc.dg/c2x-tag-10.c | 31 ++
gcc/testsuite/gcc.dg/c2x-tag-2.c | 43 +++
gcc/testsuite/gcc.dg/c2x-tag-3.c | 16
gcc/testsuite/gcc.dg/c2x-tag-4.c | 19 +
gcc/testsuite/gcc.dg/c2x-tag-5.c | 26
gcc/testsuite/gcc.dg/c2x-tag-6.c | 34
gcc/testsuite/gcc.dg/c2x-tag-7.c | 28 +
gcc/testsuite/gcc.dg/c2x-tag-8.c | 25
gcc/testsuite/gcc.dg/c2x-tag-9.c | 12 ++
14 files changed, 387 insertions(+), 16 deletions(-)
create mode 100644 gcc/testsuite/gcc.dg/c2x-tag-1.c
create mode 100644 gcc/testsuite/gcc.dg/c2x-tag-10.c
create mode 100644 gcc/testsuite/gcc.dg/c2x-tag-2.c
create mode 100644 gcc/testsuite/gcc.dg/c2x-tag-3.c
create mode 100644 gcc/testsuite/gcc.dg/c2x-tag-4.c
create mode 100644 gcc/testsuite/gcc.dg/c2x-tag-5.c
create mode 100644 gcc/testsuite/gcc.dg/c2x-tag-6.c
create mode 100644 gcc/testsuite/gcc.dg/c2x-tag-7.c
create mode 100644 gcc/testsuite/gcc.dg/c2x-tag-8.c
create mode 100644 gcc/testsuite/gcc.dg/c2x-tag-9.c
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 1f9eb44dbaa..c5c6a853fa9 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -1993,6 +1993,24 @@ locate_old_decl (tree decl)
decl, TREE_TYPE (decl));
}
+static tree
+previous_tag (tree type)
+{
+ struct c_binding *b = NULL;
+ tree name = TYPE_NAME (type);
+
+ if (name)
+b = I_TAG_BINDING (name);
+
+ if (b)
+b = b->shadowed;
+
+ if (b && B_IN_CURRENT_SCOPE (b))
+return b->decl;
+
+ return NULL_TREE;
+}
+
/* Subroutine of duplicate_decls. Compare NEWDECL to OLDDECL.
Returns true if the caller should proceed to merge the two, false
if OLDDECL should simply be discarded. As a side effect, issues
@@ -8442,11 +8460,14 @@ get_parm_info (bool ellipsis, tree expr)
if (TREE_CODE (decl) != UNION_TYPE || b->id != NULL_TREE)
{
if (b->id)
- /* The %s will be one of 'struct', 'union', or 'enum'. */
- warning_at (b->locus, 0,
- "%<%s %E%> declared inside parameter list"
- " will not be visible outside of this definition or"
- " declaration", keyword, b->id);
+ {
+ /* The %s will be one of 'struct', 'union', or 'enum'. */
+ if (!flag_isoc2x)
+ warning_at (b->locus, 0,
+ "%<%s %E%> declared inside parameter list"
+ " will not be visible outside of this
definition or"
+ " declaration", keyword, b->id);
+ }
else
/* The %s will be one of 'struct', 'union', or 'enum'. */
warning_at (b->locus, 0,
@@ -8651,6 +8672,12 @@ start_struct (location_t loc, enum tree_code code, tree
name,
if (name != NULL_TREE)
ref = lookup_tag (code, name, true, );
+
+ /* For C2X, even if we already have a completed definition,
+ we do not use it. We will check for consistency later. */
+ if (flag_isoc2x && ref && TYPE_SIZE (ref))
+ref = NULL_TREE;
+
if (ref && TREE_CODE (ref) == code)
{
if (TYPE_STUB_DECL (ref))
@@ -9439,6 +9466,25 @@ finish_struct (location_t loc, tree t, tree fieldlist,
tree attributes,
warning_at (loc, 0, "union cannot be made transparent");
}
+ /* Check for consistency with previous definition */
+ if (flag_isoc2x)
+{
+ tree vistype = previous_tag (t);
+ if (vistype
+ && TREE_CODE (vistype) == TREE_CODE (t)
+ &&