public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Martin Uecker <uecker@tugraz.at>
To: gcc-patches@gcc.gnu.org
Cc: Joseph Myers <joseph@codesourcery.com>
Subject: [C PATCH 4/6] c23: tag compatibility rules for enums
Date: Sat, 26 Aug 2023 18:24:04 +0200	[thread overview]
Message-ID: <525f0f422f6d907b415d42e16daf8acdbd92ebe6.camel@tugraz.at> (raw)
In-Reply-To: <4b3866a8cc9b48f3be97c004dedbac8e9149da63.camel@tugraz.at>



Allow redefinition of enum types and enumerators.

gcc/c:
	* c-decl.cc (start_num): Allow redefinition.
	(finish_enum): Diagnose conflicts.
	(build_enumerator): Set context.
	(diagnose_mismatched_decls): Diagnose conflicting enumerators.
	(push_decl): Preserve context for enumerators.

gcc/testsuide/:
	* gcc.dg/c2x-tag-enum-1.c: New test.
	* gcc.dg/c2x-tag-enum-2.c: New test.
	* gcc.dg/c2x-tag-enum-3.c: New test.
	* gcc.dg/c2x-tag-enum-4.c: New test.
---
 gcc/c/c-decl.cc                       | 47 ++++++++++++++++++++--
 gcc/c/c-typeck.cc                     |  5 ++-
 gcc/testsuite/gcc.dg/c2x-tag-enum-1.c | 56 +++++++++++++++++++++++++++
 gcc/testsuite/gcc.dg/c2x-tag-enum-2.c | 23 +++++++++++
 gcc/testsuite/gcc.dg/c2x-tag-enum-3.c |  7 ++++
 gcc/testsuite/gcc.dg/c2x-tag-enum-4.c | 22 +++++++++++
 6 files changed, 155 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/c2x-tag-enum-1.c
 create mode 100644 gcc/testsuite/gcc.dg/c2x-tag-enum-2.c
 create mode 100644 gcc/testsuite/gcc.dg/c2x-tag-enum-3.c
 create mode 100644 gcc/testsuite/gcc.dg/c2x-tag-enum-4.c

diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index c5c6a853fa9..b514e8a35ee 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -2064,9 +2064,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_isoc2x
+	  && 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;
     }
 
@@ -3227,8 +3242,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;
@@ -9606,9 +9624,15 @@ 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 (flag_isoc2x && enumtype != NULL_TREE
+      && TREE_CODE (enumtype) == ENUMERAL_TYPE
+      && 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)
 	{
@@ -9868,6 +9892,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_isoc2x)
+    {
+      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;
@@ -10047,6 +10085,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);
diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index 802c727d9d3..2b79cbba950 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -1396,6 +1396,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);
@@ -6895,7 +6898,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/c2x-tag-enum-1.c b/gcc/testsuite/gcc.dg/c2x-tag-enum-1.c
new file mode 100644
index 00000000000..d66d30d356f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-tag-enum-1.c
@@ -0,0 +1,56 @@
+/*
+ * { dg-do compile }
+ * { dg-options "-std=c2x" }
+ */
+
+// 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*: 0, default: 2)
+};
+
+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/c2x-tag-enum-2.c b/gcc/testsuite/gcc.dg/c2x-tag-enum-2.c
new file mode 100644
index 00000000000..bbe872c1480
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-tag-enum-2.c
@@ -0,0 +1,23 @@
+/*
+ * { dg-do compile }
+ * { dg-options "-std=c2x" }
+ */
+
+// incomplete during construction
+
+enum A { B = 7 } y;
+enum A { B = 7 };
+
+enum A { B = _Generic(&y, enum A*: 1, default: 7) };
+
+void g(void)
+{
+	enum A { B = _Generic(&y, enum A*: 1, default: 7) };
+	_Static_assert(7 == B, "");
+}
+
+enum X { E = 1, F = 1 + 1 };
+enum X { F = 2, E = 1 };
+
+
+
diff --git a/gcc/testsuite/gcc.dg/c2x-tag-enum-3.c b/gcc/testsuite/gcc.dg/c2x-tag-enum-3.c
new file mode 100644
index 00000000000..6f65bb73ef6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-tag-enum-3.c
@@ -0,0 +1,7 @@
+/* { dg-do compile }
+ * { dg-options "-std=c2x" }
+ */
+
+enum A { N = 0 * sizeof(enum A { M = 1 }) }; 	/* { dg-error "nested" } */
+
+
diff --git a/gcc/testsuite/gcc.dg/c2x-tag-enum-4.c b/gcc/testsuite/gcc.dg/c2x-tag-enum-4.c
new file mode 100644
index 00000000000..413b1fe8110
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-tag-enum-4.c
@@ -0,0 +1,22 @@
+/* { dg-do compile }
+ * { dg-options "-std=c2x" }
+ */
+
+// 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;
+}
+
-- 
2.30.2



  parent reply	other threads:[~2023-08-26 16:24 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-08-26 16:19 c23 type compatibility rules, v2 Martin Uecker
2023-08-26 16:20 ` [C PATCH 1/6] c: reorganize recursive type checking Martin Uecker
2023-09-06 20:59   ` Joseph Myers
2023-09-10  8:17     ` [C PATCH 1/6 v2] " Martin Uecker
2023-09-11 20:28       ` Joseph Myers
2023-08-26 16:22 ` [C PATCH 2/6] c23: recursive type checking of tagged type Martin Uecker
2023-11-07 23:06   ` Joseph Myers
2023-08-26 16:23 ` [C PATCH 3/6] c23: tag compatibility rules for struct and unions Martin Uecker
2023-11-07 23:18   ` Joseph Myers
2023-08-26 16:24 ` Martin Uecker [this message]
2023-11-07 23:20   ` [C PATCH 4/6] c23: tag compatibility rules for enums Joseph Myers
2023-08-26 16:25 ` [C PATCH 5/6] c23: aliasing of compatible tagged types Martin Uecker
2023-08-26 16:26 ` [C PATCH 6/6] c23: construct composite type for " Martin Uecker
2023-11-07 23:45   ` Joseph Myers
2023-08-26 16:26 ` [C PATCH] c: flag for tag compatibility rules Martin Uecker

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=525f0f422f6d907b415d42e16daf8acdbd92ebe6.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).