From: Martin Uecker <uecker@tugraz.at>
To: gcc-patches@gcc.gnu.org
Cc: Joseph Myers <joseph@codesourcery.com>
Subject: [V4] [PATCH 2/4] c23: tag compatibility rules for enums
Date: Mon, 27 Nov 2023 14:16:36 +0100 [thread overview]
Message-ID: <ab4cbf4e4f83f5d4e4e77280b7135c900daa0549.camel@tugraz.at> (raw)
In-Reply-To: <02a9b94e4d653b6f1b9f89a1b62187f46e871738.camel@tugraz.at>
(only tests were changed)
c23: tag compatibility rules for enums
Allow redefinition of enum types and enumerators. Diagnose
nested redefinitions including redefinitions in the enum
specifier for enum types with fixed underlying type.
gcc/c:
* c-tree.h (c_parser_enum_specifier): Add parameter.
* c-decl.cc (start_enum): Allow redefinition.
(finish_enum): Diagnose conflicts.
(build_enumerator): Set context.
(diagnose_mismatched_decls): Diagnose conflicting enumerators.
(push_decl): Preserve context for enumerators.
* c-parser.cc (c_parser_enum_specifier): Remember when
seen is from an enum type which is not yet defined.
gcc/testsuide/:
* gcc.dg/c23-tag-enum-1.c: New test.
* gcc.dg/c23-tag-enum-2.c: New test.
* gcc.dg/c23-tag-enum-3.c: New test.
* gcc.dg/c23-tag-enum-4.c: New test.
* gcc.dg/c23-tag-enum-5.c: New test.
* gcc.dg/gnu23-tag-enum-1.c: Mew test.
---
gcc/c/c-decl.cc | 65 +++++++++++++++++++++----
gcc/c/c-parser.cc | 5 +-
gcc/c/c-tree.h | 3 +-
gcc/c/c-typeck.cc | 5 +-
gcc/testsuite/gcc.dg/c23-tag-enum-1.c | 56 +++++++++++++++++++++
gcc/testsuite/gcc.dg/c23-tag-enum-2.c | 17 +++++++
gcc/testsuite/gcc.dg/c23-tag-enum-3.c | 7 +++
gcc/testsuite/gcc.dg/c23-tag-enum-4.c | 22 +++++++++
gcc/testsuite/gcc.dg/c23-tag-enum-5.c | 18 +++++++
gcc/testsuite/gcc.dg/gnu23-tag-enum-1.c | 19 ++++++++
10 files changed, 205 insertions(+), 12 deletions(-)
create mode 100644 gcc/testsuite/gcc.dg/c23-tag-enum-1.c
create mode 100644 gcc/testsuite/gcc.dg/c23-tag-enum-2.c
create mode 100644 gcc/testsuite/gcc.dg/c23-tag-enum-3.c
create mode 100644 gcc/testsuite/gcc.dg/c23-tag-enum-4.c
create mode 100644 gcc/testsuite/gcc.dg/c23-tag-enum-5.c
create mode 100644 gcc/testsuite/gcc.dg/gnu23-tag-enum-1.c
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index ebe1708b977..bcc09ba479e 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -2114,9 +2114,24 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
given scope. */
if (TREE_CODE (olddecl) == CONST_DECL)
{
- auto_diagnostic_group d;
- error ("redeclaration of enumerator %q+D", newdecl);
- locate_old_decl (olddecl);
+ if (flag_isoc23
+ && TYPE_NAME (DECL_CONTEXT (newdecl))
+ && DECL_CONTEXT (newdecl) != DECL_CONTEXT (olddecl)
+ && TYPE_NAME (DECL_CONTEXT (newdecl)) == TYPE_NAME (DECL_CONTEXT (olddecl)))
+ {
+ if (!simple_cst_equal (DECL_INITIAL (olddecl), DECL_INITIAL (newdecl)))
+ {
+ auto_diagnostic_group d;
+ error ("conflicting redeclaration of enumerator %q+D", newdecl);
+ locate_old_decl (olddecl);
+ }
+ }
+ else
+ {
+ auto_diagnostic_group d;
+ error ("redeclaration of enumerator %q+D", newdecl);
+ locate_old_decl (olddecl);
+ }
return false;
}
@@ -3277,8 +3292,11 @@ pushdecl (tree x)
/* Must set DECL_CONTEXT for everything not at file scope or
DECL_FILE_SCOPE_P won't work. Local externs don't count
- unless they have initializers (which generate code). */
+ unless they have initializers (which generate code). We
+ also exclude CONST_DECLs because enumerators will get the
+ type of the enum as context. */
if (current_function_decl
+ && TREE_CODE (x) != CONST_DECL
&& (!VAR_OR_FUNCTION_DECL_P (x)
|| DECL_INITIAL (x) || !TREE_PUBLIC (x)))
DECL_CONTEXT (x) = current_function_decl;
@@ -9747,7 +9765,7 @@ layout_array_type (tree t)
tree
start_enum (location_t loc, struct c_enum_contents *the_enum, tree name,
- tree fixed_underlying_type)
+ tree fixed_underlying_type, bool potential_nesting_p)
{
tree enumtype = NULL_TREE;
location_t enumloc = UNKNOWN_LOCATION;
@@ -9759,9 +9777,26 @@ start_enum (location_t loc, struct c_enum_contents *the_enum, tree name,
if (name != NULL_TREE)
enumtype = lookup_tag (ENUMERAL_TYPE, name, true, &enumloc);
+ if (enumtype != NULL_TREE && TREE_CODE (enumtype) == ENUMERAL_TYPE)
+ {
+ /* If the type is currently being defined or if we have seen an
+ incomplete version which is now complete, this is a nested
+ redefinition. The later happens if the redefinition occurs
+ inside the enum specifier itself. */
+ if (C_TYPE_BEING_DEFINED (enumtype)
+ || (potential_nesting_p && TYPE_VALUES (enumtype) != NULL_TREE))
+ error_at (loc, "nested redefinition of %<enum %E%>", name);
+
+ /* For C23 we allow redefinitions. We set to zero and check for
+ consistency later. */
+ if (flag_isoc23 && TYPE_VALUES (enumtype) != NULL_TREE)
+ enumtype = NULL_TREE;
+ }
+
if (enumtype == NULL_TREE || TREE_CODE (enumtype) != ENUMERAL_TYPE)
{
enumtype = make_node (ENUMERAL_TYPE);
+ TYPE_SIZE (enumtype) = NULL_TREE;
pushtag (loc, name, enumtype);
if (fixed_underlying_type != NULL_TREE)
{
@@ -9789,9 +9824,6 @@ start_enum (location_t loc, struct c_enum_contents *the_enum, tree name,
DECL_SOURCE_LOCATION (TYPE_STUB_DECL (enumtype)) = loc;
}
- if (C_TYPE_BEING_DEFINED (enumtype))
- error_at (loc, "nested redefinition of %<enum %E%>", name);
-
C_TYPE_BEING_DEFINED (enumtype) = 1;
if (TYPE_VALUES (enumtype) != NULL_TREE)
@@ -10021,6 +10053,20 @@ finish_enum (tree enumtype, tree values, tree attributes)
&& !in_sizeof && !in_typeof && !in_alignof)
struct_parse_info->struct_types.safe_push (enumtype);
+ /* Check for consistency with previous definition */
+ if (flag_isoc23)
+ {
+ tree vistype = previous_tag (enumtype);
+ if (vistype
+ && TREE_CODE (vistype) == TREE_CODE (enumtype)
+ && !C_TYPE_BEING_DEFINED (vistype))
+ {
+ TYPE_STUB_DECL (vistype) = TYPE_STUB_DECL (enumtype);
+ if (!comptypes_same_p (enumtype, vistype))
+ error("conflicting redefinition of enum %qT", enumtype);
+ }
+ }
+
C_TYPE_BEING_DEFINED (enumtype) = 0;
return enumtype;
@@ -10200,6 +10246,7 @@ build_enumerator (location_t decl_loc, location_t loc,
decl = build_decl (decl_loc, CONST_DECL, name, TREE_TYPE (value));
DECL_INITIAL (decl) = value;
+ DECL_CONTEXT (decl) = the_enum->enum_type;
pushdecl (decl);
return tree_cons (decl, value, NULL_TREE);
@@ -10216,7 +10263,7 @@ c_simulate_enum_decl (location_t loc, const char *name,
struct c_enum_contents the_enum;
tree enumtype = start_enum (loc, &the_enum, get_identifier (name),
- NULL_TREE);
+ NULL_TREE, false);
tree value_chain = NULL_TREE;
string_int_pair *value;
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index 703f9570dbc..ff30ba198ca 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -3667,6 +3667,7 @@ c_parser_enum_specifier (c_parser *parser)
{
struct c_typespec ret;
bool have_std_attrs;
+ bool potential_nesting_p = false;
tree std_attrs = NULL_TREE;
tree attrs;
tree ident = NULL_TREE;
@@ -3706,6 +3707,7 @@ c_parser_enum_specifier (c_parser *parser)
if (!ENUM_FIXED_UNDERLYING_TYPE_P (ret.spec))
error_at (enum_loc, "%<enum%> declared both with and without "
"fixed underlying type");
+ potential_nesting_p = NULL_TREE == TYPE_VALUES (ret.spec);
}
else
{
@@ -3776,7 +3778,8 @@ c_parser_enum_specifier (c_parser *parser)
forward order at the end. */
tree values;
timevar_push (TV_PARSE_ENUM);
- type = start_enum (enum_loc, &the_enum, ident, fixed_underlying_type);
+ type = start_enum (enum_loc, &the_enum, ident, fixed_underlying_type,
+ potential_nesting_p);
values = NULL_TREE;
c_parser_consume_token (parser);
while (true)
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index 7df4d65bf7a..a5dd9a37944 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -682,7 +682,8 @@ extern void c_warn_unused_attributes (tree);
extern tree c_warn_type_attributes (tree);
extern void shadow_tag (const struct c_declspecs *);
extern void shadow_tag_warned (const struct c_declspecs *, int);
-extern tree start_enum (location_t, struct c_enum_contents *, tree, tree);
+extern tree start_enum (location_t, struct c_enum_contents *, tree, tree,
+ bool potential_nesting_p);
extern bool start_function (struct c_declspecs *, struct c_declarator *, tree);
extern tree start_decl (struct c_declarator *, struct c_declspecs *, bool,
tree, bool = true, location_t * = NULL);
diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index dc8a16df272..8116c9b3e68 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -1419,6 +1419,9 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree t2,
{
case ENUMERAL_TYPE:
{
+ if (!comptypes (ENUM_UNDERLYING_TYPE (t1), ENUM_UNDERLYING_TYPE (t2)))
+ return false;
+
/* Speed up the case where the type values are in the same order. */
tree tv1 = TYPE_VALUES (t1);
tree tv2 = TYPE_VALUES (t2);
@@ -6948,7 +6951,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
if (checktype != error_mark_node
&& TREE_CODE (checktype) == ENUMERAL_TYPE
&& TREE_CODE (type) == ENUMERAL_TYPE
- && TYPE_MAIN_VARIANT (checktype) != TYPE_MAIN_VARIANT (type))
+ && !comptypes (TYPE_MAIN_VARIANT (checktype), TYPE_MAIN_VARIANT (type)))
{
gcc_rich_location loc (location);
warning_at (&loc, OPT_Wenum_conversion,
diff --git a/gcc/testsuite/gcc.dg/c23-tag-enum-1.c b/gcc/testsuite/gcc.dg/c23-tag-enum-1.c
new file mode 100644
index 00000000000..58933cfac24
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c23-tag-enum-1.c
@@ -0,0 +1,56 @@
+/*
+ * { dg-do compile }
+ * { dg-options "-std=c23" }
+ */
+
+// incompatible redeclarations, conflicing redefinitions
+
+
+enum aa { A = 1 } *a;
+enum bb { B = 1 } *b;
+
+void test(void)
+{
+ enum aa { A = 1 } *c = a;
+ enum bb { B = 2 } *d = b; /* { dg-warning "incompatible pointer type" } */
+}
+
+enum cc { C = 1 };
+enum cc { D = 1 }; /* { dg-error "conflicting redefinition" } */
+
+enum dd { E = 1 };
+enum dd { E = 2 }; /* { dg-error "conflicting redefinition" } */
+ /* { dg-error "redeclaration of enumerator" "" { target *-*-* } .-1 } */
+
+
+
+void test2(void)
+{
+ enum ee *a;
+ enum ee { F = 2 } *b;
+ b = a;
+}
+
+
+enum ff { G = 2 };
+enum gg { G = 2 }; /* { dg-error "redeclaration of enumerator" } */
+enum g2 { G = 3 }; /* { dg-error "redeclaration of enumerator" } */
+
+enum hh { H = 1, H = 1 }; /* { dg-error "redeclaration of enumerator" } */
+
+enum ss { K = 2 };
+enum ss { K = 2 };
+
+enum tt { R = 2 } TT;
+enum tt {
+ R = _Generic(&TT, enum tt*: 2, default: 0)
+};
+
+enum { U = 1 };
+enum { U = 1 }; /* { dg-error "redeclaration of enumerator" } */
+
+enum { V = 1 };
+enum { V = 2 }; /* { dg-error "redeclaration of enumerator" } */
+
+
+
diff --git a/gcc/testsuite/gcc.dg/c23-tag-enum-2.c b/gcc/testsuite/gcc.dg/c23-tag-enum-2.c
new file mode 100644
index 00000000000..2bf7255b844
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c23-tag-enum-2.c
@@ -0,0 +1,17 @@
+/*
+ * { dg-do compile }
+ * { dg-options "-std=c23" }
+ */
+
+enum A { B = 7 } y;
+
+// complete during later construction
+
+enum A { B = _Generic(&y, enum A*: 7, default: 1) };
+
+
+enum X { E = 1, F = 1 + 1 };
+enum X { F = 2, E = 1 };
+
+
+
diff --git a/gcc/testsuite/gcc.dg/c23-tag-enum-3.c b/gcc/testsuite/gcc.dg/c23-tag-enum-3.c
new file mode 100644
index 00000000000..12218a5b911
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c23-tag-enum-3.c
@@ -0,0 +1,7 @@
+/* { dg-do compile }
+ * { dg-options "-std=c23" }
+ */
+
+enum A { N = 0 * sizeof(enum A { M = 1 }) }; /* { dg-error "nested" } */
+
+
diff --git a/gcc/testsuite/gcc.dg/c23-tag-enum-4.c b/gcc/testsuite/gcc.dg/c23-tag-enum-4.c
new file mode 100644
index 00000000000..f20dc55fc6c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c23-tag-enum-4.c
@@ -0,0 +1,22 @@
+/* { dg-do compile }
+ * { dg-options "-std=c23" }
+ */
+
+// fixed underlying types
+
+enum A : int { N = 1 } x1 = { };
+enum B : int { M = 1 } x2 = { };
+enum C { U = 1 } x3 = { };
+
+void f(void)
+{
+ enum A : int { N = 1 } y1 = x1;
+ enum B : short { M = 1 } y2;
+ y2 = x2;
+ enum B : short { M = 1 } y2b;
+ enum Bb : short { V = 1 } y2d = x2;
+ enum B : short { M = 1 } *y2e = &x2; /* { dg-warning "incompatible" } */
+ enum B : short { M = 1 } y2c = x2;
+ enum C { U = 1 } y3 = x3;
+}
+
diff --git a/gcc/testsuite/gcc.dg/c23-tag-enum-5.c b/gcc/testsuite/gcc.dg/c23-tag-enum-5.c
new file mode 100644
index 00000000000..22ce06fb80d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c23-tag-enum-5.c
@@ -0,0 +1,18 @@
+/* { dg-do compile }
+ * { dg-options "-std=c23" } */
+
+// test for nested redefinitions of enums
+
+void foo(void)
+{
+ enum e { A = 1 };
+ enum e { A = 1 /* { dg-error "redeclaration" } */
+ + 0 * sizeof(enum e { A = 1 }) }; /* { dg-error "nested redefinition" } */
+
+}
+
+typedef __SIZE_TYPE__ size_t;
+enum f : typeof (sizeof (enum f : size_t { B })) { B }; /* { dg-error "nested redefinition" } */
+
+
+
diff --git a/gcc/testsuite/gcc.dg/gnu23-tag-enum-1.c b/gcc/testsuite/gcc.dg/gnu23-tag-enum-1.c
new file mode 100644
index 00000000000..6b346ed35a0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gnu23-tag-enum-1.c
@@ -0,0 +1,19 @@
+/*
+ * { dg-do compile }
+ * { dg-options "-std=gnu23" }
+ */
+
+
+enum A { B = 7 } y;
+
+void g(void)
+{
+ // incomplete during construction
+ // this is a GNU extension because enum A is used
+ // before the type is completed.
+
+ enum A { B = _Generic(&y, enum A*: 1, default: 7) };
+ _Static_assert(7 == B, "");
+}
+
+
--
2.39.2
next prev parent reply other threads:[~2023-11-27 13:16 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 ` [PATCH 4/4] c23: construct composite type for " Martin Uecker
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 ` Martin Uecker [this message]
2023-12-14 20:58 ` [V4] [PATCH 2/4] c23: tag compatibility rules for enums 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=ab4cbf4e4f83f5d4e4e77280b7135c900daa0549.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).