https://gcc.gnu.org/g:abcfe1e51c18b14d324586f1d9d50e8238497865

commit r15-4766-gabcfe1e51c18b14d324586f1d9d50e8238497865
Author: Jakub Jelinek <ja...@redhat.com>
Date:   Wed Oct 30 07:59:52 2024 +0100

    c: Add C2Y N3370 - Case range expressions support [PR117021]
    
    The following patch adds the C2Y N3370 paper support.
    We had the case ranges as a GNU extension for decades, so this patch
    simply:
    1) adds different diagnostics when it is used in C (depending on flag_isoc2y
       and pedantic and warn_c23_c2y_compat)
    2) emits a pedwarn in C if in a range conversion changes the value of
       the low or high bounds and in that case doesn't emit -Woverflow and
       similar warnings anymore if the pedwarn has been diagnosed
    3) changes the handling of empty ranges both in C and C++; previously
       we just warned but let the values be still looked up in the splay
       tree/entered into it (and let only gimplification throw away those
       empty cases), so e.g. case -6 ... -8: break; case -6: break;
       complained about duplicate case label.  But that actually isn't
       duplicate case label, case -6 ... -8: stands for nothing at all
       and that is how it is treated later on (thrown away)
    
    2024-10-30  Jakub Jelinek  <ja...@redhat.com>
    
            PR c/117021
    gcc/c-family/
            * c-common.cc (c_add_case_label): Emit different diagnostics for C
            on case ranges.  Diagnose for C using pedwarn conversions of range
            expressions changing value and don't emit further conversion
            diagnostics if the pedwarn has been diagnosed.  For empty ranges
            bail out after emitting warning, don't add anything into splay
            trees nor add a CASE_LABEL_EXPR.
    gcc/testsuite/
            * gcc.dg/switch-6.c: Expect different diagnostics.  Add -std=gnu23
            to dg-options.
            * gcc.dg/switch-7.c: Expect different diagnostics.  Add -std=c23
            to dg-options.
            * gcc.dg/gnu23-switch-1.c: New test.
            * gcc.dg/gnu23-switch-2.c: New test.
            * gcc.dg/c23-switch-1.c: New test.
            * gcc.dg/c2y-switch-1.c: New test.
            * gcc.dg/c2y-switch-2.c: New test.
            * gcc.dg/c2y-switch-3.c: New test.

Diff:
---
 gcc/c-family/c-common.cc              |  46 +++++++++++++++-
 gcc/testsuite/gcc.dg/c23-switch-1.c   | 100 ++++++++++++++++++++++++++++++++++
 gcc/testsuite/gcc.dg/c2y-switch-1.c   |  89 ++++++++++++++++++++++++++++++
 gcc/testsuite/gcc.dg/c2y-switch-2.c   | 100 ++++++++++++++++++++++++++++++++++
 gcc/testsuite/gcc.dg/c2y-switch-3.c   |  40 ++++++++++++++
 gcc/testsuite/gcc.dg/gnu23-switch-1.c | 100 ++++++++++++++++++++++++++++++++++
 gcc/testsuite/gcc.dg/gnu23-switch-2.c |  89 ++++++++++++++++++++++++++++++
 gcc/testsuite/gcc.dg/switch-6.c       |   4 +-
 gcc/testsuite/gcc.dg/switch-7.c       |   4 +-
 9 files changed, 565 insertions(+), 7 deletions(-)

diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc
index f7feb21f70e5..06be2a37b4f6 100644
--- a/gcc/c-family/c-common.cc
+++ b/gcc/c-family/c-common.cc
@@ -5186,13 +5186,41 @@ c_add_case_label (location_t loc, splay_tree cases, 
tree cond,
 
   /* Case ranges are a GNU extension.  */
   if (high_value)
-    pedwarn (loc, OPT_Wpedantic,
-            "range expressions in switch statements are non-standard");
+    {
+      if (c_dialect_cxx ())
+       pedwarn (loc, OPT_Wpedantic,
+                "range expressions in switch statements are non-standard");
+      else if (warn_c23_c2y_compat > 0)
+       {
+         if (pedantic && !flag_isoc2y)
+           pedwarn (loc, OPT_Wc23_c2y_compat,
+                    "ISO C does not support range expressions in switch "
+                    "statements before C2Y");
+         else
+           warning_at (loc, OPT_Wc23_c2y_compat,
+                       "ISO C does not support range expressions in switch "
+                       "statements before C2Y");
+       }
+      else if (warn_c23_c2y_compat && pedantic && !flag_isoc2y)
+       pedwarn (loc, OPT_Wpedantic,
+                "ISO C does not support range expressions in switch "
+                "statements before C2Y");
+    }
 
   type = TREE_TYPE (cond);
   if (low_value)
     {
       low_value = check_case_value (loc, low_value);
+      tree tem = NULL_TREE;
+      if (high_value
+         && !c_dialect_cxx ()
+         && low_value != error_mark_node
+         && !int_fits_type_p (low_value, type)
+         && pedwarn (loc, OPT_Wpedantic,
+                     "conversion of %qE to %qT in range expression changes "
+                     "value to %qE", low_value, type,
+                     (tem = fold_convert (type, low_value))))
+       low_value = tem;
       low_value = convert_and_check (loc, type, low_value);
       low_value = fold (low_value);
       if (low_value == error_mark_node)
@@ -5201,6 +5229,15 @@ c_add_case_label (location_t loc, splay_tree cases, tree 
cond,
   if (high_value)
     {
       high_value = check_case_value (loc, high_value);
+      tree tem = NULL_TREE;
+      if (!c_dialect_cxx ()
+         && high_value != error_mark_node
+         && !int_fits_type_p (high_value, type)
+         && pedwarn (loc, OPT_Wpedantic,
+                     "conversion of %qE to %qT in range expression changes "
+                     "value to %qE", high_value, type,
+                     (tem = fold_convert (type, high_value))))
+       high_value = tem;
       high_value = convert_and_check (loc, type, high_value);
       high_value = fold (high_value);
       if (high_value == error_mark_node)
@@ -5215,7 +5252,10 @@ c_add_case_label (location_t loc, splay_tree cases, tree 
cond,
       if (tree_int_cst_equal (low_value, high_value))
        high_value = NULL_TREE;
       else if (!tree_int_cst_lt (low_value, high_value))
-       warning_at (loc, 0, "empty range specified");
+       {
+         warning_at (loc, 0, "empty range specified");
+         goto error_out;
+       }
     }
 
   /* Look up the LOW_VALUE in the table of case labels we already
diff --git a/gcc/testsuite/gcc.dg/c23-switch-1.c 
b/gcc/testsuite/gcc.dg/c23-switch-1.c
new file mode 100644
index 000000000000..c47dc51740bc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c23-switch-1.c
@@ -0,0 +1,100 @@
+/* C2Y N3370 - Case range expressions.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c23 -pedantic-errors -W -Wall" } */
+
+enum E { F = 10, G = 20 };
+
+void
+foo (unsigned x)
+{
+  switch (x)
+    {
+    case -1:
+      break;
+    case ~0U + 1ULL:                   /* { dg-warning "conversion from 'long 
long unsigned int' to 'unsigned int' changes value from '\[0-9]*' to '0'" } */
+      break;
+    default:
+      break;
+    }
+}
+
+void
+bar (unsigned x)
+{
+  switch (x)
+    {
+    case -2 ... -1:                    /* { dg-error "ISO C does not support 
range expressions in switch statements before C2Y" } */
+                                       /* { dg-error "conversion of '-2' to 
'unsigned int' in range expression changes value to '\[0-9]*'" "" { target 
*-*-* } .-1 } */
+                                       /* { dg-error "conversion of '-1' to 
'unsigned int' in range expression changes value to '\[0-9]*'" "" { target 
*-*-* } .-2 } */
+      break;
+    case ~0U + 1ULL ... ~0U + 2ULL:    /* { dg-error "ISO C does not support 
range expressions in switch statements before C2Y" } */
+                                       /* { dg-error "conversion of '\[0-9]*' 
to 'unsigned int' in range expression changes value to '0'" "" { target *-*-* } 
.-1 } */
+                                       /* { dg-error "conversion of '\[0-9]*' 
to 'unsigned int' in range expression changes value to '1'" "" { target *-*-* } 
.-2 } */
+      break;
+    case 70 ... 70:                    /* { dg-error "ISO C does not support 
range expressions in switch statements before C2Y" } */
+      break;
+    case 80 ... 78:                    /* { dg-error "ISO C does not support 
range expressions in switch statements before C2Y" } */
+                                       /* { dg-warning "empty range specified" 
"" { target *-*-* } .-1 } */
+      break;
+    case -4 ... -4:                    /* { dg-error "ISO C does not support 
range expressions in switch statements before C2Y" } */
+                                       /* { dg-error "conversion of '-4' to 
'unsigned int' in range expression changes value to '\[0-9]*'" "" { target 
*-*-* } .-1 } */
+      break;
+    case ~0U + 6ULL ... ~0U + 6ULL:    /* { dg-error "ISO C does not support 
range expressions in switch statements before C2Y" } */
+                                       /* { dg-error "conversion of '\[0-9]*' 
to 'unsigned int' in range expression changes value to '5'" "" { target *-*-* } 
.-1 } */
+      break;
+    default:
+      break;
+    }
+}
+
+void
+baz (unsigned char x)
+{
+  switch (x)
+    {
+    case -32 ... -30:                  /* { dg-error "ISO C does not support 
range expressions in switch statements before C2Y" } */
+                                       /* { dg-warning "case label value is 
less than minimum value for type" "" { target *-*-* } .-1 } */
+      break;
+    case -31:                          /* { dg-error "duplicate case value" } 
*/
+      break;
+    case -42:                          /* { dg-warning "case label value is 
less than minimum value for type" } */
+      break;
+    case -43 ... -41:                  /* { dg-error "ISO C does not support 
range expressions in switch statements before C2Y" } */
+                                       /* { dg-error "duplicate \\\(or 
overlapping\\\) case value" "" { target *-*-* } .-1 } */
+      break;
+    default:
+      break;
+    }
+}
+
+void
+qux (int x)
+{
+  switch (x)
+    {
+    case -6 ... -8:                    /* { dg-error "ISO C does not support 
range expressions in switch statements before C2Y" } */
+                                       /* { dg-warning "empty range specified" 
"" { target *-*-* } .-1 } */
+      break;
+    case -6:
+      break;
+    case -7:
+      break;
+    case -8:
+      break;
+    case F...G:                                /* { dg-error "ISO C does not 
support range expressions in switch statements before C2Y" } */
+      break;
+    case -10:
+      break;
+    case -10 ... -11:                  /* { dg-error "ISO C does not support 
range expressions in switch statements before C2Y" } */
+                                       /* { dg-warning "empty range specified" 
"" { target *-*-* } .-1 } */
+      break;
+    case -14 ... -15:                  /* { dg-error "ISO C does not support 
range expressions in switch statements before C2Y" } */
+                                       /* { dg-warning "empty range specified" 
"" { target *-*-* } .-1 } */
+      break;
+    case -14 ... -15:                  /* { dg-error "ISO C does not support 
range expressions in switch statements before C2Y" } */
+                                       /* { dg-warning "empty range specified" 
"" { target *-*-* } .-1 } */
+      break;
+    default:
+      break;
+    }
+}
diff --git a/gcc/testsuite/gcc.dg/c2y-switch-1.c 
b/gcc/testsuite/gcc.dg/c2y-switch-1.c
new file mode 100644
index 000000000000..d3ef5c344b99
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2y-switch-1.c
@@ -0,0 +1,89 @@
+/* C2Y N3370 - Case range expressions.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c2y -pedantic -W -Wall" } */
+
+enum E { F = 10, G = 20 };
+
+void
+foo (unsigned x)
+{
+  switch (x)
+    {
+    case -1:
+      break;
+    case ~0U + 1ULL:                   /* { dg-warning "conversion from 'long 
long unsigned int' to 'unsigned int' changes value from '\[0-9]*' to '0'" } */
+      break;
+    default:
+      break;
+    }
+}
+
+void
+bar (unsigned x)
+{
+  switch (x)
+    {
+    case -2 ... -1:                    /* { dg-warning "conversion of '-2' to 
'unsigned int' in range expression changes value to '\[0-9]*'" } */
+                                       /* { dg-warning "conversion of '-1' to 
'unsigned int' in range expression changes value to '\[0-9]*'" "" { target 
*-*-* } .-1 } */
+      break;
+    case ~0U + 1ULL ... ~0U + 2ULL:    /* { dg-warning "conversion of 
'\[0-9]*' to 'unsigned int' in range expression changes value to '0'" } */
+                                       /* { dg-warning "conversion of 
'\[0-9]*' to 'unsigned int' in range expression changes value to '1'" "" { 
target *-*-* } .-1 } */
+      break;
+    case 70 ... 70:
+      break;
+    case 80 ... 78:                    /* { dg-warning "empty range specified" 
} */
+      break;
+    case -4 ... -4:                    /* { dg-warning "conversion of '-4' to 
'unsigned int' in range expression changes value to '\[0-9]*'" } */
+      break;
+    case ~0U + 6ULL ... ~0U + 6ULL:    /* { dg-warning "conversion of 
'\[0-9]*' to 'unsigned int' in range expression changes value to '5'" } */
+      break;
+    default:
+      break;
+    }
+}
+
+void
+baz (unsigned char x)
+{
+  switch (x)
+    {
+    case -32 ... -30:                  /* { dg-warning "case label value is 
less than minimum value for type" } */
+      break;
+    case -31:                          /* { dg-error "duplicate case value" } 
*/
+      break;
+    case -42:                          /* { dg-warning "case label value is 
less than minimum value for type" } */
+      break;
+    case -43 ... -41:                  /* { dg-error "duplicate \\\(or 
overlapping\\\) case value" } */
+      break;
+    default:
+      break;
+    }
+}
+
+void
+qux (int x)
+{
+  switch (x)
+    {
+    case -6 ... -8:                    /* { dg-warning "empty range specified" 
} */
+      break;
+    case -6:
+      break;
+    case -7:
+      break;
+    case -8:
+      break;
+    case F...G:
+      break;
+    case -10:
+      break;
+    case -10 ... -11:                  /* { dg-warning "empty range specified" 
} */
+      break;
+    case -14 ... -15:                  /* { dg-warning "empty range specified" 
} */
+      break;
+    case -14 ... -15:                  /* { dg-warning "empty range specified" 
} */
+      break;
+    default:
+      break;
+    }
+}
diff --git a/gcc/testsuite/gcc.dg/c2y-switch-2.c 
b/gcc/testsuite/gcc.dg/c2y-switch-2.c
new file mode 100644
index 000000000000..9ef4d40922c7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2y-switch-2.c
@@ -0,0 +1,100 @@
+/* C2Y N3370 - Case range expressions.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c2y -pedantic -W -Wall -Wc23-c2y-compat" } */
+
+enum E { F = 10, G = 20 };
+
+void
+foo (unsigned x)
+{
+  switch (x)
+    {
+    case -1:
+      break;
+    case ~0U + 1ULL:                   /* { dg-warning "conversion from 'long 
long unsigned int' to 'unsigned int' changes value from '\[0-9]*' to '0'" } */
+      break;
+    default:
+      break;
+    }
+}
+
+void
+bar (unsigned x)
+{
+  switch (x)
+    {
+    case -2 ... -1:                    /* { dg-warning "ISO C does not support 
range expressions in switch statements before C2Y" } */
+                                       /* { dg-warning "conversion of '-2' to 
'unsigned int' in range expression changes value to '\[0-9]*'" "" { target 
*-*-* } .-1 } */
+                                       /* { dg-warning "conversion of '-1' to 
'unsigned int' in range expression changes value to '\[0-9]*'" "" { target 
*-*-* } .-2 } */
+      break;
+    case ~0U + 1ULL ... ~0U + 2ULL:    /* { dg-warning "ISO C does not support 
range expressions in switch statements before C2Y" } */
+                                       /* { dg-warning "conversion of 
'\[0-9]*' to 'unsigned int' in range expression changes value to '0'" "" { 
target *-*-* } .-1 } */
+                                       /* { dg-warning "conversion of 
'\[0-9]*' to 'unsigned int' in range expression changes value to '1'" "" { 
target *-*-* } .-2 } */
+      break;
+    case 70 ... 70:                    /* { dg-warning "ISO C does not support 
range expressions in switch statements before C2Y" } */
+      break;
+    case 80 ... 78:                    /* { dg-warning "ISO C does not support 
range expressions in switch statements before C2Y" } */
+                                       /* { dg-warning "empty range specified" 
"" { target *-*-* } .-1 } */
+      break;
+    case -4 ... -4:                    /* { dg-warning "ISO C does not support 
range expressions in switch statements before C2Y" } */
+                                       /* { dg-warning "conversion of '-4' to 
'unsigned int' in range expression changes value to '\[0-9]*'" "" { target 
*-*-* } .-1 } */
+      break;
+    case ~0U + 6ULL ... ~0U + 6ULL:    /* { dg-warning "ISO C does not support 
range expressions in switch statements before C2Y" } */
+                                       /* { dg-warning "conversion of 
'\[0-9]*' to 'unsigned int' in range expression changes value to '5'" "" { 
target *-*-* } .-1 } */
+      break;
+    default:
+      break;
+    }
+}
+
+void
+baz (unsigned char x)
+{
+  switch (x)
+    {
+    case -32 ... -30:                  /* { dg-warning "ISO C does not support 
range expressions in switch statements before C2Y" } */
+                                       /* { dg-warning "case label value is 
less than minimum value for type" "" { target *-*-* } .-1 } */
+      break;
+    case -31:                          /* { dg-error "duplicate case value" } 
*/
+      break;
+    case -42:                          /* { dg-warning "case label value is 
less than minimum value for type" } */
+      break;
+    case -43 ... -41:                  /* { dg-warning "ISO C does not support 
range expressions in switch statements before C2Y" } */
+                                       /* { dg-error "duplicate \\\(or 
overlapping\\\) case value" "" { target *-*-* } .-1 } */
+      break;
+    default:
+      break;
+    }
+}
+
+void
+qux (int x)
+{
+  switch (x)
+    {
+    case -6 ... -8:                    /* { dg-warning "ISO C does not support 
range expressions in switch statements before C2Y" } */
+                                       /* { dg-warning "empty range specified" 
"" { target *-*-* } .-1 } */
+      break;
+    case -6:
+      break;
+    case -7:
+      break;
+    case -8:
+      break;
+    case F...G:                                /* { dg-warning "ISO C does not 
support range expressions in switch statements before C2Y" } */
+      break;
+    case -10:
+      break;
+    case -10 ... -11:                  /* { dg-warning "ISO C does not support 
range expressions in switch statements before C2Y" } */
+                                       /* { dg-warning "empty range specified" 
"" { target *-*-* } .-1 } */
+      break;
+    case -14 ... -15:                  /* { dg-warning "ISO C does not support 
range expressions in switch statements before C2Y" } */
+                                       /* { dg-warning "empty range specified" 
"" { target *-*-* } .-1 } */
+      break;
+    case -14 ... -15:                  /* { dg-warning "ISO C does not support 
range expressions in switch statements before C2Y" } */
+                                       /* { dg-warning "empty range specified" 
"" { target *-*-* } .-1 } */
+      break;
+    default:
+      break;
+    }
+}
diff --git a/gcc/testsuite/gcc.dg/c2y-switch-3.c 
b/gcc/testsuite/gcc.dg/c2y-switch-3.c
new file mode 100644
index 000000000000..3cb143a42ead
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2y-switch-3.c
@@ -0,0 +1,40 @@
+/* C2Y N3370 - Case range expressions.  */
+/* { dg-do run } */
+/* { dg-options "-std=c2y -pedantic-errors" } */
+
+extern void abort ();
+
+void
+foo (int x)
+{
+  switch (x)
+    {
+    case -42 ... 42:
+      if (x < -42 || x > 42)
+        abort ();
+      break;
+    case 43 ... 43:
+      if (x != 43)
+        abort ();
+      break;
+    case 44:
+      if (x != 44)
+        abort ();
+      break;
+    case 45 ... 46:
+      if (x < 45 || x > 46)
+        abort ();
+      break;
+    default:
+      if (x >= -42 && x <= 46)
+        abort ();
+      break;
+    }
+}
+
+int
+main ()
+{
+  for (int i = -44; i <= 48; ++i)
+    foo (i);
+}
diff --git a/gcc/testsuite/gcc.dg/gnu23-switch-1.c 
b/gcc/testsuite/gcc.dg/gnu23-switch-1.c
new file mode 100644
index 000000000000..57c3576f635d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gnu23-switch-1.c
@@ -0,0 +1,100 @@
+/* C2Y N3370 - Case range expressions.  */
+/* { dg-do compile } */
+/* { dg-options "-std=gnu23 -pedantic -W -Wall" } */
+
+enum E { F = 10, G = 20 };
+
+void
+foo (unsigned x)
+{
+  switch (x)
+    {
+    case -1:
+      break;
+    case ~0U + 1ULL:                   /* { dg-warning "conversion from 'long 
long unsigned int' to 'unsigned int' changes value from '\[0-9]*' to '0'" } */
+      break;
+    default:
+      break;
+    }
+}
+
+void
+bar (unsigned x)
+{
+  switch (x)
+    {
+    case -2 ... -1:                    /* { dg-warning "ISO C does not support 
range expressions in switch statements before C2Y" } */
+                                       /* { dg-warning "conversion of '-2' to 
'unsigned int' in range expression changes value to '\[0-9]*'" "" { target 
*-*-* } .-1 } */
+                                       /* { dg-warning "conversion of '-1' to 
'unsigned int' in range expression changes value to '\[0-9]*'" "" { target 
*-*-* } .-2 } */
+      break;
+    case ~0U + 1ULL ... ~0U + 2ULL:    /* { dg-warning "ISO C does not support 
range expressions in switch statements before C2Y" } */
+                                       /* { dg-warning "conversion of 
'\[0-9]*' to 'unsigned int' in range expression changes value to '0'" "" { 
target *-*-* } .-1 } */
+                                       /* { dg-warning "conversion of 
'\[0-9]*' to 'unsigned int' in range expression changes value to '1'" "" { 
target *-*-* } .-2 } */
+      break;
+    case 70 ... 70:                    /* { dg-warning "ISO C does not support 
range expressions in switch statements before C2Y" } */
+      break;
+    case 80 ... 78:                    /* { dg-warning "ISO C does not support 
range expressions in switch statements before C2Y" } */
+                                       /* { dg-warning "empty range specified" 
"" { target *-*-* } .-1 } */
+      break;
+    case -4 ... -4:                    /* { dg-warning "ISO C does not support 
range expressions in switch statements before C2Y" } */
+                                       /* { dg-warning "conversion of '-4' to 
'unsigned int' in range expression changes value to '\[0-9]*'" "" { target 
*-*-* } .-1 } */
+      break;
+    case ~0U + 6ULL ... ~0U + 6ULL:    /* { dg-warning "ISO C does not support 
range expressions in switch statements before C2Y" } */
+                                       /* { dg-warning "conversion of 
'\[0-9]*' to 'unsigned int' in range expression changes value to '5'" "" { 
target *-*-* } .-1 } */
+      break;
+    default:
+      break;
+    }
+}
+
+void
+baz (unsigned char x)
+{
+  switch (x)
+    {
+    case -32 ... -30:                  /* { dg-warning "ISO C does not support 
range expressions in switch statements before C2Y" } */
+                                       /* { dg-warning "case label value is 
less than minimum value for type" "" { target *-*-* } .-1 } */
+      break;
+    case -31:                          /* { dg-error "duplicate case value" } 
*/
+      break;
+    case -42:                          /* { dg-warning "case label value is 
less than minimum value for type" } */
+      break;
+    case -43 ... -41:                  /* { dg-warning "ISO C does not support 
range expressions in switch statements before C2Y" } */
+                                       /* { dg-error "duplicate \\\(or 
overlapping\\\) case value" "" { target *-*-* } .-1 } */
+      break;
+    default:
+      break;
+    }
+}
+
+void
+qux (int x)
+{
+  switch (x)
+    {
+    case -6 ... -8:                    /* { dg-warning "ISO C does not support 
range expressions in switch statements before C2Y" } */
+                                       /* { dg-warning "empty range specified" 
"" { target *-*-* } .-1 } */
+      break;
+    case -6:
+      break;
+    case -7:
+      break;
+    case -8:
+      break;
+    case F...G:                                /* { dg-warning "ISO C does not 
support range expressions in switch statements before C2Y" } */
+      break;
+    case -10:
+      break;
+    case -10 ... -11:                  /* { dg-warning "ISO C does not support 
range expressions in switch statements before C2Y" } */
+                                       /* { dg-warning "empty range specified" 
"" { target *-*-* } .-1 } */
+      break;
+    case -14 ... -15:                  /* { dg-warning "ISO C does not support 
range expressions in switch statements before C2Y" } */
+                                       /* { dg-warning "empty range specified" 
"" { target *-*-* } .-1 } */
+      break;
+    case -14 ... -15:                  /* { dg-warning "ISO C does not support 
range expressions in switch statements before C2Y" } */
+                                       /* { dg-warning "empty range specified" 
"" { target *-*-* } .-1 } */
+      break;
+    default:
+      break;
+    }
+}
diff --git a/gcc/testsuite/gcc.dg/gnu23-switch-2.c 
b/gcc/testsuite/gcc.dg/gnu23-switch-2.c
new file mode 100644
index 000000000000..47dd67bab52e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gnu23-switch-2.c
@@ -0,0 +1,89 @@
+/* C2Y N3370 - Case range expressions.  */
+/* { dg-do compile } */
+/* { dg-options "-std=gnu23 -pedantic -W -Wall -Wno-c23-c2y-compat" } */
+
+enum E { F = 10, G = 20 };
+
+void
+foo (unsigned x)
+{
+  switch (x)
+    {
+    case -1:
+      break;
+    case ~0U + 1ULL:                   /* { dg-warning "conversion from 'long 
long unsigned int' to 'unsigned int' changes value from '\[0-9]*' to '0'" } */
+      break;
+    default:
+      break;
+    }
+}
+
+void
+bar (unsigned x)
+{
+  switch (x)
+    {
+    case -2 ... -1:                    /* { dg-warning "conversion of '-2' to 
'unsigned int' in range expression changes value to '\[0-9]*'" } */
+                                       /* { dg-warning "conversion of '-1' to 
'unsigned int' in range expression changes value to '\[0-9]*'" "" { target 
*-*-* } .-1 } */
+      break;
+    case ~0U + 1ULL ... ~0U + 2ULL:    /* { dg-warning "conversion of 
'\[0-9]*' to 'unsigned int' in range expression changes value to '0'" } */
+                                       /* { dg-warning "conversion of 
'\[0-9]*' to 'unsigned int' in range expression changes value to '1'" "" { 
target *-*-* } .-1 } */
+      break;
+    case 70 ... 70:
+      break;
+    case 80 ... 78:                    /* { dg-warning "empty range specified" 
} */
+      break;
+    case -4 ... -4:                    /* { dg-warning "conversion of '-4' to 
'unsigned int' in range expression changes value to '\[0-9]*'" } */
+      break;
+    case ~0U + 6ULL ... ~0U + 6ULL:    /* { dg-warning "conversion of 
'\[0-9]*' to 'unsigned int' in range expression changes value to '5'" } */
+      break;
+    default:
+      break;
+    }
+}
+
+void
+baz (unsigned char x)
+{
+  switch (x)
+    {
+    case -32 ... -30:                  /* { dg-warning "case label value is 
less than minimum value for type" } */
+      break;
+    case -31:                          /* { dg-error "duplicate case value" } 
*/
+      break;
+    case -42:                          /* { dg-warning "case label value is 
less than minimum value for type" } */
+      break;
+    case -43 ... -41:                  /* { dg-error "duplicate \\\(or 
overlapping\\\) case value" } */
+      break;
+    default:
+      break;
+    }
+}
+
+void
+qux (int x)
+{
+  switch (x)
+    {
+    case -6 ... -8:                    /* { dg-warning "empty range specified" 
} */
+      break;
+    case -6:
+      break;
+    case -7:
+      break;
+    case -8:
+      break;
+    case F...G:
+      break;
+    case -10:
+      break;
+    case -10 ... -11:                  /* { dg-warning "empty range specified" 
} */
+      break;
+    case -14 ... -15:                  /* { dg-warning "empty range specified" 
} */
+      break;
+    case -14 ... -15:                  /* { dg-warning "empty range specified" 
} */
+      break;
+    default:
+      break;
+    }
+}
diff --git a/gcc/testsuite/gcc.dg/switch-6.c b/gcc/testsuite/gcc.dg/switch-6.c
index 25d1d96b2687..24ff49837caa 100644
--- a/gcc/testsuite/gcc.dg/switch-6.c
+++ b/gcc/testsuite/gcc.dg/switch-6.c
@@ -2,13 +2,13 @@
    for case ranges with -pedantic.  */
 /* Origin: Joseph Myers <jos...@codesourcery.com> */
 /* { dg-do compile } */
-/* { dg-options "-pedantic" } */
+/* { dg-options "-pedantic -std=gnu23" } */
 
 void
 f (int a)
 {
   switch (a)
     {
-    case 0 ... 0: ; /* { dg-warning "range expressions in switch statements 
are non-standard" } */
+    case 0 ... 0: ; /* { dg-warning "ISO C does not support range expressions 
in switch statements before C2Y" } */
     }
 }
diff --git a/gcc/testsuite/gcc.dg/switch-7.c b/gcc/testsuite/gcc.dg/switch-7.c
index 29cb82569914..05b1fb805214 100644
--- a/gcc/testsuite/gcc.dg/switch-7.c
+++ b/gcc/testsuite/gcc.dg/switch-7.c
@@ -2,13 +2,13 @@
    for case ranges with -pedantic-errors.  */
 /* Origin: Joseph Myers <jos...@codesourcery.com> */
 /* { dg-do compile } */
-/* { dg-options "-pedantic-errors" } */
+/* { dg-options "-pedantic-errors -std=c23" } */
 
 void
 f (int a)
 {
   switch (a)
     {
-    case 0 ... 0: ; /* { dg-error "range expressions in switch statements are 
non-standard" } */
+    case 0 ... 0: ; /* { dg-error "ISO C does not support range expressions in 
switch statements before C2Y" } */
     }
 }

Reply via email to