public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [C PATCH, v3] Fix for redeclared enumerator initialized with different type [PR115109]
@ 2024-06-01 15:02 Martin Uecker
  2024-06-03 17:37 ` Joseph Myers
  0 siblings, 1 reply; 4+ messages in thread
From: Martin Uecker @ 2024-06-01 15:02 UTC (permalink / raw)
  To: gcc-patches; +Cc: Joseph Myers


This is a new version of the patch.  I changed the overflow warning to
an error and added your other example to the test case.

Bootstrapped and regression tested on x86_64.


    c23: Fix for redeclared enumerator initialized with different type [PR115109]
    
    c23 specifies that the type of a redeclared enumerator is the one of the
    previous declaration.  Convert initializers with different type accordingly
    and emit an error when the value does not fit.
    
    2024-06-01 Martin Uecker  <uecker@tugraz.at>
    
    PR c/115109
    
    gcc/c/
            * c-decl.cc (build_enumerator): When redeclaring an
            enumerator convert value to previous type.  For redeclared
            enumerators use underlying type for computing the next value.
    
    gcc/testsuite/
            * gcc.dg/pr115109.c: New test.
            * gcc.dg/c23-tag-enum-6.c: New test.
            * gcc.dg/c23-tag-enum-7.c: New test.

diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 64924b87a91..38a4e842307 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -10262,6 +10262,7 @@ build_enumerator (location_t decl_loc, location_t loc,
 		  struct c_enum_contents *the_enum, tree name, tree value)
 {
   tree decl;
+  tree old_decl;
 
   /* Validate and default VALUE.  */
 
@@ -10321,6 +10322,23 @@ build_enumerator (location_t decl_loc, location_t loc,
 	 definition.  */
       value = convert (the_enum->enum_type, value);
     }
+  else if (flag_isoc23
+	   && (old_decl = lookup_name_in_scope (name, current_scope))
+	   && old_decl != error_mark_node
+	   && TREE_TYPE (old_decl)
+	   && TREE_TYPE (TREE_TYPE (old_decl))
+	   && TREE_CODE (old_decl) == CONST_DECL)
+    {
+      /* Enumeration constants in a redeclaration have the previous type.  */
+      tree previous_type = TREE_TYPE (DECL_INITIAL (old_decl));
+      if (!int_fits_type_p (value, previous_type))
+	{
+	  error_at (loc, "value of redeclared enumerator outside the range "
+			 "of %qT", previous_type);
+	  locate_old_decl (old_decl);
+	}
+      value = convert (previous_type, value);
+    }
   else
     {
       /* Even though the underlying type of an enum is unspecified, the
@@ -10387,9 +10405,14 @@ build_enumerator (location_t decl_loc, location_t loc,
 			     false);
     }
   else
-    the_enum->enum_next_value
-      = build_binary_op (EXPR_LOC_OR_LOC (value, input_location),
-			 PLUS_EXPR, value, integer_one_node, false);
+    {
+      /* In a redeclaration the type can already be the enumeral type.  */
+      if (TREE_CODE (TREE_TYPE (value)) == ENUMERAL_TYPE)
+	value = convert (ENUM_UNDERLYING_TYPE (TREE_TYPE (value)), value);
+      the_enum->enum_next_value
+	= build_binary_op (EXPR_LOC_OR_LOC (value, input_location),
+			   PLUS_EXPR, value, integer_one_node, false);
+    }
   the_enum->enum_overflow = tree_int_cst_lt (the_enum->enum_next_value, value);
   if (the_enum->enum_overflow
       && !ENUM_FIXED_UNDERLYING_TYPE_P (the_enum->enum_type))
diff --git a/gcc/testsuite/gcc.dg/c23-tag-enum-6.c b/gcc/testsuite/gcc.dg/c23-tag-enum-6.c
new file mode 100644
index 00000000000..0fa5d7534f3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c23-tag-enum-6.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c23" } */
+
+#include <limits.h>
+
+enum E : int { a = 1, b = 2 };
+enum E : int { b = _Generic(a, enum E: 2), a = 1 };
+
+enum H { x = 1 };
+enum H { x = 2UL + UINT_MAX };		/* { dg-error "outside the range" } */
+
+enum K : int { z = 1 };
+enum K : int { z = 2UL + UINT_MAX };	/* { dg-error "outside the range" } */
+
+enum F { A = 0, B = UINT_MAX };
+enum F { B = UINT_MAX, A };		/* { dg-error "outside the range" } */
+
+enum G : unsigned int { C = 0, D = UINT_MAX };
+enum G : unsigned int { D = UINT_MAX, C };		/* { dg-error "overflow" } */
+
diff --git a/gcc/testsuite/gcc.dg/c23-tag-enum-7.c b/gcc/testsuite/gcc.dg/c23-tag-enum-7.c
new file mode 100644
index 00000000000..0634c0aa698
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c23-tag-enum-7.c
@@ -0,0 +1,41 @@
+/* { dg-do compile }
+ * { dg-options "-std=c23" } */
+
+#include <limits.h>
+
+// enumerators are all representable in int
+enum E { a = 1UL, b = _Generic(a, int: 2) };
+static_assert(_Generic(a, int: 1));
+static_assert(_Generic(b, int: 1));
+enum E { a = 1UL, b = _Generic(a, int: 2) };
+static_assert(_Generic(a, int: 1));
+static_assert(_Generic(b, int: 1));
+
+// enumerators are not representable in int
+enum H { c = 1UL << (UINT_WIDTH + 1), d = 2 };
+static_assert(_Generic(c, enum H: 1));
+static_assert(_Generic(d, enum H: 1));
+enum H { c = 1UL << (UINT_WIDTH + 1), d = _Generic(c, enum H: 2) };
+static_assert(_Generic(c, enum H: 1));
+static_assert(_Generic(d, enum H: 1));
+
+// there is an overflow in the first declaration
+enum K { e = UINT_MAX, f, g = _Generic(e, unsigned int: 0) + _Generic(f, unsigned long: 1) };
+static_assert(_Generic(e, enum K: 1));
+static_assert(_Generic(f, enum K: 1));
+static_assert(_Generic(g, enum K: 1));
+enum K { e = UINT_MAX, f, g = _Generic(e, enum K: 0) + _Generic(f, enum K: 1) };
+static_assert(_Generic(e, enum K: 1));
+static_assert(_Generic(f, enum K: 1));
+static_assert(_Generic(g, enum K: 1));
+
+// there is an overflow in the first declaration
+enum U { k = INT_MAX, l, m = _Generic(k, int: 0) + _Generic(l, long: 1) };
+static_assert(_Generic(k, enum U: 1));
+static_assert(_Generic(l, enum U: 1));
+static_assert(_Generic(m, enum U: 1));
+enum U { k = INT_MAX, l, m = _Generic(k, enum U: 0) + _Generic(l, enum U: 1) };
+static_assert(_Generic(k, enum U: 1));
+static_assert(_Generic(l, enum U: 1));
+static_assert(_Generic(m, enum U: 1));
+
diff --git a/gcc/testsuite/gcc.dg/pr115109.c b/gcc/testsuite/gcc.dg/pr115109.c
new file mode 100644
index 00000000000..961197d0c71
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr115109.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c23" } */
+
+#include <limits.h>
+
+enum E { a = 1UL << (ULONG_WIDTH - 5), b = 2 };
+enum E { a = 1ULL << (ULONG_WIDTH - 5), b = _Generic(a, enum E: 2) };
+


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [C PATCH, v3] Fix for redeclared enumerator initialized with different type [PR115109]
  2024-06-01 15:02 [C PATCH, v3] Fix for redeclared enumerator initialized with different type [PR115109] Martin Uecker
@ 2024-06-03 17:37 ` Joseph Myers
  2024-06-15 15:11   ` Martin Uecker
  0 siblings, 1 reply; 4+ messages in thread
From: Joseph Myers @ 2024-06-03 17:37 UTC (permalink / raw)
  To: Martin Uecker; +Cc: gcc-patches

On Sat, 1 Jun 2024, Martin Uecker wrote:

> This is a new version of the patch.  I changed the overflow warning to
> an error and added your other example to the test case.
> 
> Bootstrapped and regression tested on x86_64.
> 
> 
>     c23: Fix for redeclared enumerator initialized with different type [PR115109]
>     
>     c23 specifies that the type of a redeclared enumerator is the one of the
>     previous declaration.  Convert initializers with different type accordingly
>     and emit an error when the value does not fit.
>     
>     2024-06-01 Martin Uecker  <uecker@tugraz.at>
>     
>     PR c/115109
>     
>     gcc/c/
>             * c-decl.cc (build_enumerator): When redeclaring an
>             enumerator convert value to previous type.  For redeclared
>             enumerators use underlying type for computing the next value.
>     
>     gcc/testsuite/
>             * gcc.dg/pr115109.c: New test.
>             * gcc.dg/c23-tag-enum-6.c: New test.
>             * gcc.dg/c23-tag-enum-7.c: New test.

OK.

-- 
Joseph S. Myers
josmyers@redhat.com


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [C PATCH, v3] Fix for redeclared enumerator initialized with different type [PR115109]
  2024-06-03 17:37 ` Joseph Myers
@ 2024-06-15 15:11   ` Martin Uecker
  2024-06-17 18:54     ` Joseph Myers
  0 siblings, 1 reply; 4+ messages in thread
From: Martin Uecker @ 2024-06-15 15:11 UTC (permalink / raw)
  To: Joseph Myers; +Cc: gcc-patches


The patch fails on arm because the tests make assumptions
about enums that are not true everywhere. Should we just 
limit the tests to x86?

Martin

Am Montag, dem 03.06.2024 um 17:37 +0000 schrieb Joseph Myers:
> On Sat, 1 Jun 2024, Martin Uecker wrote:
> 
> > This is a new version of the patch.  I changed the overflow warning to
> > an error and added your other example to the test case.
> > 
> > Bootstrapped and regression tested on x86_64.
> > 
> > 
> >     c23: Fix for redeclared enumerator initialized with different type [PR115109]
> >     
> >     c23 specifies that the type of a redeclared enumerator is the one of the
> >     previous declaration.  Convert initializers with different type accordingly
> >     and emit an error when the value does not fit.
> >     
> >     2024-06-01 Martin Uecker  <uecker@tugraz.at>
> >     
> >     PR c/115109
> >     
> >     gcc/c/
> >             * c-decl.cc (build_enumerator): When redeclaring an
> >             enumerator convert value to previous type.  For redeclared
> >             enumerators use underlying type for computing the next value.
> >     
> >     gcc/testsuite/
> >             * gcc.dg/pr115109.c: New test.
> >             * gcc.dg/c23-tag-enum-6.c: New test.
> >             * gcc.dg/c23-tag-enum-7.c: New test.
> 
> OK.
> 


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [C PATCH, v3] Fix for redeclared enumerator initialized with different type [PR115109]
  2024-06-15 15:11   ` Martin Uecker
@ 2024-06-17 18:54     ` Joseph Myers
  0 siblings, 0 replies; 4+ messages in thread
From: Joseph Myers @ 2024-06-17 18:54 UTC (permalink / raw)
  To: Martin Uecker; +Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 495 bytes --]

On Sat, 15 Jun 2024, Martin Uecker wrote:

> The patch fails on arm because the tests make assumptions
> about enums that are not true everywhere. Should we just 
> limit the tests to x86?

For compilation tests, using -fno-short-enums should work.  That won't 
work for link / execute tests, but in those cases you can use { target { ! 
short_enums } }.  (If there are other issues beyond a short-enums default, 
other effective-targets may be needed.)

-- 
Joseph S. Myers
josmyers@redhat.com

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2024-06-17 18:55 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-06-01 15:02 [C PATCH, v3] Fix for redeclared enumerator initialized with different type [PR115109] Martin Uecker
2024-06-03 17:37 ` Joseph Myers
2024-06-15 15:11   ` Martin Uecker
2024-06-17 18:54     ` Joseph Myers

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).