[C++] PR c++/90875 - added -Wswitch-outside-range option.

Message ID CAOrE4X1xBChcxA+A9kh-jcJz1uXZS5rTyDCuMRTpN-TZn8JyeA@mail.gmail.com
State New
Headers show
Series
  • [C++] PR c++/90875 - added -Wswitch-outside-range option.
Related show

Commit Message

Matthew Beliveau June 17, 2019, 5:26 p.m.
This patch adds a new warning option: Wswitch-outside-range, so that
users are able to selectively control the warning. The warning is
enabled by default.

Best,
Matthew Beliveau

Comments

Jakub Jelinek June 17, 2019, 5:31 p.m. | #1
On Mon, Jun 17, 2019 at 01:26:37PM -0400, Matthew Beliveau wrote:
> 2019-06-14  Matthew Beliveau  <mbelivea@redhat.com>

> 	

> 	PR c++/90875 - added -Wswitch-outside-range option

> 	* doc/invoke.texi (Wswitch-outside-range): Document.

> 

> 	* c-warn.c (c_do_switch_warnings): Implemented new Wswitch-outside-range

> 	warning option.

> 	

> 	* c.opt (Wswitch-outside-range): Added new option.

> 

> 	* g++.dg/warn/Wswitch-outside-range-1.C: New test.

> 	* g++.dg/warn/Wswitch-outside-range-2.C: New test.

> 	* g++.dg/warn/Wswitch-outside-range-3.C: New test.

> 	* g++.dg/warn/Wswitch-outside-range-4.C: New test.

> 

> diff --git gcc/c-family/c-warn.c gcc/c-family/c-warn.c

> index 5941c10cddb..b61694af638 100644

> --- gcc/c-family/c-warn.c

> +++ gcc/c-family/c-warn.c

> @@ -1460,8 +1460,9 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location,

>  				       min_value) >= 0)

>  	    {

>  	      location_t loc = EXPR_LOCATION ((tree) node->value);

> -	      warning_at (loc, 0, "lower value in case label range"

> -				  " less than minimum value for type");

> +	      warning_at (loc, OPT_Wswitch_outside_range, "lower value in case"

> +				  " label range less than minimum value"

> +				  " for type");


Just a formatting nit, not a review.  Previously the indentation of the
second part of the string literal made sense, now it doesn't, it shouldn't
start at a location that is not related in any way to the previous line.
Best move the whole string literal to the second line, like:
	      warning_at (loc, OPT_Wswitch_outside_range,
			  "lower value in case label range less than minimum"
			  " value for type");
Happens multiple times in the patch.

	Jakub
Marek Polacek June 17, 2019, 5:44 p.m. | #2
Thanks for the patch.

On Mon, Jun 17, 2019 at 01:26:37PM -0400, Matthew Beliveau wrote:
> --- gcc/c-family/c.opt

> +++ gcc/c-family/c.opt

> @@ -819,6 +819,10 @@ Wswitch-bool

>  C ObjC C++ ObjC++ Var(warn_switch_bool) Warning Init(1)

>  Warn about switches with boolean controlling expression.

>  

> +Wswitch-outside-range

> +C++ ObjC++ Var(warn_switch_outside_range) Warning Init(1)


This warning is not C++- specific; it also applies to C and Obj-C.

> +Warn about switch values that are outside of their type's range.


This is slightly imprecise -- the values are outside of the type
of the controlling expression of the switch.  So I'd say
"that are outside of the switch's type range" or so.

> diff --git gcc/doc/invoke.texi gcc/doc/invoke.texi

> index bf9da0f0a6e..c23496b2668 100644

> --- gcc/doc/invoke.texi

> +++ gcc/doc/invoke.texi

> @@ -5390,6 +5390,12 @@ switch ((int) (a == 4))

>  @end smallexample

>  This warning is enabled by default for C and C++ programs.

>  

> +@item -Wswitch-outside-range

> +@opindex Wswitch-outside-range

> +@opindex Wno-switch-outside-range

> +Warn whenever a @code{switch} state has a value that is outside of it's


"its"

> +respective type range.

> +


This should also say
"This warning is enabled by default for C and C++ programs."

> diff --git gcc/testsuite/g++.dg/warn/Wswitch-outside-range-1.C gcc/testsuite/g++.dg/warn/Wswitch-outside-range-1.C

> new file mode 100644

> index 00000000000..29e56f3ba2d

> --- /dev/null

> +++ gcc/testsuite/g++.dg/warn/Wswitch-outside-range-1.C

> @@ -0,0 +1,8 @@

> +// PR c++/90875

> +

> +void f(char c)

> +{

> +  switch (c)

> +    case 300: // { dg-warning "case label value exceeds maximum value for type" }

> +    case -300:; // { dg-warning "case label value is less than minimum value for type" }

> +}

> diff --git gcc/testsuite/g++.dg/warn/Wswitch-outside-range-2.C gcc/testsuite/g++.dg/warn/Wswitch-outside-range-2.C

> new file mode 100644

> index 00000000000..20cc019b209

> --- /dev/null

> +++ gcc/testsuite/g++.dg/warn/Wswitch-outside-range-2.C

> @@ -0,0 +1,9 @@

> +// PR c++/90875

> +// { dg-options -Wno-switch-outside-range }

> +

> +void f(char c)

> +{

> +  switch (c)

> +    case 300: //{ dg-bogus "case label value is less than minimum value for type" }

> +    case -300:; // { dg-bogus "case label value is less than minimum value for type" }

> +}

> diff --git gcc/testsuite/g++.dg/warn/Wswitch-outside-range-3.C gcc/testsuite/g++.dg/warn/Wswitch-outside-range-3.C

> new file mode 100644

> index 00000000000..baf15561af0

> --- /dev/null

> +++ gcc/testsuite/g++.dg/warn/Wswitch-outside-range-3.C

> @@ -0,0 +1,9 @@

> +// PR c++/90875

> +// { dg-options -Wno-pedantic }

> +

> +void f(char c)

> +{

> +  switch (c)

> +  

> +    case -300 ... 300:; // { dg-warning "lower value in case label range less than minimum value for type|upper value in case label range exceeds maximum value for type" }

> +}

> diff --git gcc/testsuite/g++.dg/warn/Wswitch-outside-range-4.C gcc/testsuite/g++.dg/warn/Wswitch-outside-range-4.C

> new file mode 100644

> index 00000000000..d9bd756dc50

> --- /dev/null

> +++ gcc/testsuite/g++.dg/warn/Wswitch-outside-range-4.C

> @@ -0,0 +1,9 @@

> +// PR c++/90875

> +// { dg-options "-Wno-pedantic -Wno-switch-outside-range" }


(You can also use __extension__ so that you don't need -Wno-pedantic.)

> +void f(char c)

> +{

> +  switch (c)

> +  

> +    case -300 ... 300:; // { dg-bogus "lower value in case label range less than minimum value for type|upper value in case label range exceeds maximum value for type" }

> +}


The tests belong to c-c++-common/ because we want to test both the C and
C++ compilers.

Please also fix the formatting as Jakub suggested.

Thanks,
--
Marek Polacek • Red Hat, Inc. • 300 A St, Boston, MA
Matthew Beliveau June 18, 2019, 5:17 p.m. | #3
Hello,

This patch should change the formatting, and move the test files into
the appropriate directory!

Thank you

On Mon, Jun 17, 2019 at 1:45 PM Marek Polacek <polacek@redhat.com> wrote:
>

> Thanks for the patch.

>

> On Mon, Jun 17, 2019 at 01:26:37PM -0400, Matthew Beliveau wrote:

> > --- gcc/c-family/c.opt

> > +++ gcc/c-family/c.opt

> > @@ -819,6 +819,10 @@ Wswitch-bool

> >  C ObjC C++ ObjC++ Var(warn_switch_bool) Warning Init(1)

> >  Warn about switches with boolean controlling expression.

> >

> > +Wswitch-outside-range

> > +C++ ObjC++ Var(warn_switch_outside_range) Warning Init(1)

>

> This warning is not C++- specific; it also applies to C and Obj-C.

>

> > +Warn about switch values that are outside of their type's range.

>

> This is slightly imprecise -- the values are outside of the type

> of the controlling expression of the switch.  So I'd say

> "that are outside of the switch's type range" or so.

>

> > diff --git gcc/doc/invoke.texi gcc/doc/invoke.texi

> > index bf9da0f0a6e..c23496b2668 100644

> > --- gcc/doc/invoke.texi

> > +++ gcc/doc/invoke.texi

> > @@ -5390,6 +5390,12 @@ switch ((int) (a == 4))

> >  @end smallexample

> >  This warning is enabled by default for C and C++ programs.

> >

> > +@item -Wswitch-outside-range

> > +@opindex Wswitch-outside-range

> > +@opindex Wno-switch-outside-range

> > +Warn whenever a @code{switch} state has a value that is outside of it's

>

> "its"

>

> > +respective type range.

> > +

>

> This should also say

> "This warning is enabled by default for C and C++ programs."

>

> > diff --git gcc/testsuite/g++.dg/warn/Wswitch-outside-range-1.C gcc/testsuite/g++.dg/warn/Wswitch-outside-range-1.C

> > new file mode 100644

> > index 00000000000..29e56f3ba2d

> > --- /dev/null

> > +++ gcc/testsuite/g++.dg/warn/Wswitch-outside-range-1.C

> > @@ -0,0 +1,8 @@

> > +// PR c++/90875

> > +

> > +void f(char c)

> > +{

> > +  switch (c)

> > +    case 300: // { dg-warning "case label value exceeds maximum value for type" }

> > +    case -300:; // { dg-warning "case label value is less than minimum value for type" }

> > +}

> > diff --git gcc/testsuite/g++.dg/warn/Wswitch-outside-range-2.C gcc/testsuite/g++.dg/warn/Wswitch-outside-range-2.C

> > new file mode 100644

> > index 00000000000..20cc019b209

> > --- /dev/null

> > +++ gcc/testsuite/g++.dg/warn/Wswitch-outside-range-2.C

> > @@ -0,0 +1,9 @@

> > +// PR c++/90875

> > +// { dg-options -Wno-switch-outside-range }

> > +

> > +void f(char c)

> > +{

> > +  switch (c)

> > +    case 300: //{ dg-bogus "case label value is less than minimum value for type" }

> > +    case -300:; // { dg-bogus "case label value is less than minimum value for type" }

> > +}

> > diff --git gcc/testsuite/g++.dg/warn/Wswitch-outside-range-3.C gcc/testsuite/g++.dg/warn/Wswitch-outside-range-3.C

> > new file mode 100644

> > index 00000000000..baf15561af0

> > --- /dev/null

> > +++ gcc/testsuite/g++.dg/warn/Wswitch-outside-range-3.C

> > @@ -0,0 +1,9 @@

> > +// PR c++/90875

> > +// { dg-options -Wno-pedantic }

> > +

> > +void f(char c)

> > +{

> > +  switch (c)

> > +

> > +    case -300 ... 300:; // { dg-warning "lower value in case label range less than minimum value for type|upper value in case label range exceeds maximum value for type" }

> > +}

> > diff --git gcc/testsuite/g++.dg/warn/Wswitch-outside-range-4.C gcc/testsuite/g++.dg/warn/Wswitch-outside-range-4.C

> > new file mode 100644

> > index 00000000000..d9bd756dc50

> > --- /dev/null

> > +++ gcc/testsuite/g++.dg/warn/Wswitch-outside-range-4.C

> > @@ -0,0 +1,9 @@

> > +// PR c++/90875

> > +// { dg-options "-Wno-pedantic -Wno-switch-outside-range" }

>

> (You can also use __extension__ so that you don't need -Wno-pedantic.)

>

> > +void f(char c)

> > +{

> > +  switch (c)

> > +

> > +    case -300 ... 300:; // { dg-bogus "lower value in case label range less than minimum value for type|upper value in case label range exceeds maximum value for type" }

> > +}

>

> The tests belong to c-c++-common/ because we want to test both the C and

> C++ compilers.

>

> Please also fix the formatting as Jakub suggested.

>

> Thanks,

> --

> Marek Polacek • Red Hat, Inc. • 300 A St, Boston, MA
Bootstrapped/regtested on x86_64-linux, ok for trunk?

2019-06-18  Matthew Beliveau  <mbelivea@redhat.com>

	PR c++/90875 - added -Wswitch-outside-range option
	* doc/invoke.texi (Wswitch-outside-range): Document.

	* c-warn.c (c_do_switch_warnings): Implemented new Wswitch-outside-range
	warning option.

	* c.opt (Wswitch-outside-range): Added new option.
	
	* c-c++-common/Wswitch-outside-range-1.C: New test.
	* c-c++-common/Wswitch-outside-range-2.C: New test.
	* c-c++-common/Wswitch-outside-range-3.C: New test.
	* c-c++-common/Wswitch-outside-range-4.C: New test.

diff --git gcc/c-family/c-warn.c gcc/c-family/c-warn.c
index 5941c10cddb..743099c75ca 100644
--- gcc/c-family/c-warn.c
+++ gcc/c-family/c-warn.c
@@ -1460,8 +1460,9 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location,
 				       min_value) >= 0)
 	    {
 	      location_t loc = EXPR_LOCATION ((tree) node->value);
-	      warning_at (loc, 0, "lower value in case label range"
-				  " less than minimum value for type");
+	      warning_at (loc, OPT_Wswitch_outside_range,
+		     "lower value in case label range less than minimum value"
+		     " for type");
 	      CASE_LOW ((tree) node->value) = convert (TREE_TYPE (cond),
 						       min_value);
 	      node->key = (splay_tree_key) CASE_LOW ((tree) node->value);
@@ -1474,8 +1475,8 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location,
 	      if (node == NULL || !node->key)
 		break;
 	      location_t loc = EXPR_LOCATION ((tree) node->value);
-	      warning_at (loc, 0, "case label value is less than minimum "
-				  "value for type");
+	      warning_at (loc, OPT_Wswitch_outside_range, "case label value is"
+				  " less than minimum value for type");
 	      splay_tree_remove (cases, node->key);
 	    }
 	  while (1);
@@ -1491,8 +1492,8 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location,
 				   max_value) > 0)
 	{
 	  location_t loc = EXPR_LOCATION ((tree) node->value);
-	  warning_at (loc, 0, "upper value in case label range"
-			      " exceeds maximum value for type");
+	  warning_at (loc, OPT_Wswitch_outside_range, "upper value in case"
+			      " label range exceeds maximum value for type");
 	  CASE_HIGH ((tree) node->value)
 	    = convert (TREE_TYPE (cond), max_value);
 	  outside_range_p = true;
@@ -1503,7 +1504,7 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location,
 	     != NULL)
 	{
 	  location_t loc = EXPR_LOCATION ((tree) node->value);
-	  warning_at (loc, 0,
+	  warning_at (loc, OPT_Wswitch_outside_range,
 		      "case label value exceeds maximum value for type");
 	  splay_tree_remove (cases, node->key);
 	  outside_range_p = true;
diff --git gcc/c-family/c.opt gcc/c-family/c.opt
index 572cf186262..4ced767ca99 100644
--- gcc/c-family/c.opt
+++ gcc/c-family/c.opt
@@ -819,6 +819,10 @@ Wswitch-bool
 C ObjC C++ ObjC++ Var(warn_switch_bool) Warning Init(1)
 Warn about switches with boolean controlling expression.
 
+Wswitch-outside-range
+C++ ObjC++ Var(warn_switch_outside_range) Warning Init(1)
+Warn about switch values that are outside of their type's range.
+
 Wtemplates
 C++ ObjC++ Var(warn_templates) Warning
 Warn on primary template declaration.
diff --git gcc/doc/invoke.texi gcc/doc/invoke.texi
index eaef4cd63d2..7872c9b0736 100644
--- gcc/doc/invoke.texi
+++ gcc/doc/invoke.texi
@@ -5390,6 +5390,12 @@ switch ((int) (a == 4))
 @end smallexample
 This warning is enabled by default for C and C++ programs.
 
+@item -Wswitch-outside-range
+@opindex Wswitch-outside-range
+@opindex Wno-switch-outside-range
+Warn whenever a @code{switch} state has a value that is outside of it's
+respective type range.
+
 @item -Wswitch-unreachable
 @opindex Wswitch-unreachable
 @opindex Wno-switch-unreachable
diff --git gcc/testsuite/c-c++-common/Wswitch-outside-range-1.C gcc/testsuite/c-c++-common/Wswitch-outside-range-1.C
new file mode 100644
index 00000000000..29e56f3ba2d
--- /dev/null
+++ gcc/testsuite/c-c++-common/Wswitch-outside-range-1.C
@@ -0,0 +1,8 @@
+// PR c++/90875
+
+void f(char c)
+{
+  switch (c)
+    case 300: // { dg-warning "case label value exceeds maximum value for type" }
+    case -300:; // { dg-warning "case label value is less than minimum value for type" }
+}
diff --git gcc/testsuite/c-c++-common/Wswitch-outside-range-2.C gcc/testsuite/c-c++-common/Wswitch-outside-range-2.C
new file mode 100644
index 00000000000..20cc019b209
--- /dev/null
+++ gcc/testsuite/c-c++-common/Wswitch-outside-range-2.C
@@ -0,0 +1,9 @@
+// PR c++/90875
+// { dg-options -Wno-switch-outside-range }
+
+void f(char c)
+{
+  switch (c)
+    case 300: //{ dg-bogus "case label value is less than minimum value for type" }
+    case -300:; // { dg-bogus "case label value is less than minimum value for type" }
+}
diff --git gcc/testsuite/c-c++-common/Wswitch-outside-range-3.C gcc/testsuite/c-c++-common/Wswitch-outside-range-3.C
new file mode 100644
index 00000000000..baf15561af0
--- /dev/null
+++ gcc/testsuite/c-c++-common/Wswitch-outside-range-3.C
@@ -0,0 +1,9 @@
+// PR c++/90875
+// { dg-options -Wno-pedantic }
+
+void f(char c)
+{
+  switch (c)
+  
+    case -300 ... 300:; // { dg-warning "lower value in case label range less than minimum value for type|upper value in case label range exceeds maximum value for type" }
+}
diff --git gcc/testsuite/c-c++-common/Wswitch-outside-range-4.C gcc/testsuite/c-c++-common/Wswitch-outside-range-4.C
new file mode 100644
index 00000000000..d9bd756dc50
--- /dev/null
+++ gcc/testsuite/c-c++-common/Wswitch-outside-range-4.C
@@ -0,0 +1,9 @@
+// PR c++/90875
+// { dg-options "-Wno-pedantic -Wno-switch-outside-range" }
+
+void f(char c)
+{
+  switch (c)
+  
+    case -300 ... 300:; // { dg-bogus "lower value in case label range less than minimum value for type|upper value in case label range exceeds maximum value for type" }
+}
Marek Polacek June 18, 2019, 5:37 p.m. | #4
On Tue, Jun 18, 2019 at 01:17:10PM -0400, Matthew Beliveau wrote:
> Hello,

> 

> This patch should change the formatting, and move the test files into

> the appropriate directory!


It doesn't address my other comments, though, so please send a new version
with that fixed.

Marek
Matthew Beliveau June 20, 2019, 1:33 p.m. | #5
Sorry for the last update, I guess I didn't notice the other changes, oops!

This should have all the changes. Let me know if anything went wrong!

Thanks,
Matthew Beliveau

On Tue, Jun 18, 2019 at 1:38 PM Marek Polacek <polacek@redhat.com> wrote:
>

> On Tue, Jun 18, 2019 at 01:17:10PM -0400, Matthew Beliveau wrote:

> > Hello,

> >

> > This patch should change the formatting, and move the test files into

> > the appropriate directory!

>

> It doesn't address my other comments, though, so please send a new version

> with that fixed.

>

> Marek
Bootstrapped/regtested on x86_64-linux, ok for trunk?

2019-06-20  Matthew Beliveau  <mbelivea@redhat.com>

	PR c++/90875 - added -Wswitch-outside-range option
	* doc/invoke.texi (Wswitch-outside-range): Document.

	* c-warn.c (c_do_switch_warnings): Implemented new Wswitch-outside-range
	warning option.

	* c.opt (Wswitch-outside-range): Added new option.
	
	* c-c++-common/Wswitch-outside-range-1.C: New test.
	* c-c++-common/Wswitch-outside-range-2.C: New test.
	* c-c++-common/Wswitch-outside-range-3.C: New test.
	* c-c++-common/Wswitch-outside-range-4.C: New test.

diff --git gcc/c-family/c-warn.c gcc/c-family/c-warn.c
index 5941c10cddb..743099c75ca 100644
--- gcc/c-family/c-warn.c
+++ gcc/c-family/c-warn.c
@@ -1460,8 +1460,9 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location,
 				       min_value) >= 0)
 	    {
 	      location_t loc = EXPR_LOCATION ((tree) node->value);
-	      warning_at (loc, 0, "lower value in case label range"
-				  " less than minimum value for type");
+	      warning_at (loc, OPT_Wswitch_outside_range,
+		     "lower value in case label range less than minimum value"
+		     " for type");
 	      CASE_LOW ((tree) node->value) = convert (TREE_TYPE (cond),
 						       min_value);
 	      node->key = (splay_tree_key) CASE_LOW ((tree) node->value);
@@ -1474,8 +1475,8 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location,
 	      if (node == NULL || !node->key)
 		break;
 	      location_t loc = EXPR_LOCATION ((tree) node->value);
-	      warning_at (loc, 0, "case label value is less than minimum "
-				  "value for type");
+	      warning_at (loc, OPT_Wswitch_outside_range, "case label value is"
+				  " less than minimum value for type");
 	      splay_tree_remove (cases, node->key);
 	    }
 	  while (1);
@@ -1491,8 +1492,8 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location,
 				   max_value) > 0)
 	{
 	  location_t loc = EXPR_LOCATION ((tree) node->value);
-	  warning_at (loc, 0, "upper value in case label range"
-			      " exceeds maximum value for type");
+	  warning_at (loc, OPT_Wswitch_outside_range, "upper value in case"
+			      " label range exceeds maximum value for type");
 	  CASE_HIGH ((tree) node->value)
 	    = convert (TREE_TYPE (cond), max_value);
 	  outside_range_p = true;
@@ -1503,7 +1504,7 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location,
 	     != NULL)
 	{
 	  location_t loc = EXPR_LOCATION ((tree) node->value);
-	  warning_at (loc, 0,
+	  warning_at (loc, OPT_Wswitch_outside_range,
 		      "case label value exceeds maximum value for type");
 	  splay_tree_remove (cases, node->key);
 	  outside_range_p = true;
diff --git gcc/c-family/c.opt gcc/c-family/c.opt
index 572cf186262..a4cf3bd623d 100644
--- gcc/c-family/c.opt
+++ gcc/c-family/c.opt
@@ -819,6 +819,10 @@ Wswitch-bool
 C ObjC C++ ObjC++ Var(warn_switch_bool) Warning Init(1)
 Warn about switches with boolean controlling expression.
 
+Wswitch-outside-range
+C ObjC C++ ObjC++ Var(warn_switch_outside_range) Warning Init(1)
+Warn about switch values that are outside of the switch's type range.
+
 Wtemplates
 C++ ObjC++ Var(warn_templates) Warning
 Warn on primary template declaration.
diff --git gcc/doc/invoke.texi gcc/doc/invoke.texi
index eaef4cd63d2..210535cb84a 100644
--- gcc/doc/invoke.texi
+++ gcc/doc/invoke.texi
@@ -5390,6 +5390,13 @@ switch ((int) (a == 4))
 @end smallexample
 This warning is enabled by default for C and C++ programs.
 
+@item -Wswitch-outside-range
+@opindex Wswitch-outside-range
+@opindex Wno-switch-outside-range
+Warn whenever a @code{switch} state has a value that is outside of its
+respective type range.  This warning is enabled by default for
+C and C++ progarams.
+
 @item -Wswitch-unreachable
 @opindex Wswitch-unreachable
 @opindex Wno-switch-unreachable
diff --git gcc/testsuite/c-c++-common/Wswitch-outside-range-1.C gcc/testsuite/c-c++-common/Wswitch-outside-range-1.C
new file mode 100644
index 00000000000..29e56f3ba2d
--- /dev/null
+++ gcc/testsuite/c-c++-common/Wswitch-outside-range-1.C
@@ -0,0 +1,8 @@
+// PR c++/90875
+
+void f(char c)
+{
+  switch (c)
+    case 300: // { dg-warning "case label value exceeds maximum value for type" }
+    case -300:; // { dg-warning "case label value is less than minimum value for type" }
+}
diff --git gcc/testsuite/c-c++-common/Wswitch-outside-range-2.C gcc/testsuite/c-c++-common/Wswitch-outside-range-2.C
new file mode 100644
index 00000000000..20cc019b209
--- /dev/null
+++ gcc/testsuite/c-c++-common/Wswitch-outside-range-2.C
@@ -0,0 +1,9 @@
+// PR c++/90875
+// { dg-options -Wno-switch-outside-range }
+
+void f(char c)
+{
+  switch (c)
+    case 300: //{ dg-bogus "case label value is less than minimum value for type" }
+    case -300:; // { dg-bogus "case label value is less than minimum value for type" }
+}
diff --git gcc/testsuite/c-c++-common/Wswitch-outside-range-3.C gcc/testsuite/c-c++-common/Wswitch-outside-range-3.C
new file mode 100644
index 00000000000..baf15561af0
--- /dev/null
+++ gcc/testsuite/c-c++-common/Wswitch-outside-range-3.C
@@ -0,0 +1,9 @@
+// PR c++/90875
+// { dg-options -Wno-pedantic }
+
+void f(char c)
+{
+  switch (c)
+  
+    case -300 ... 300:; // { dg-warning "lower value in case label range less than minimum value for type|upper value in case label range exceeds maximum value for type" }
+}
diff --git gcc/testsuite/c-c++-common/Wswitch-outside-range-4.C gcc/testsuite/c-c++-common/Wswitch-outside-range-4.C
new file mode 100644
index 00000000000..d9bd756dc50
--- /dev/null
+++ gcc/testsuite/c-c++-common/Wswitch-outside-range-4.C
@@ -0,0 +1,9 @@
+// PR c++/90875
+// { dg-options "-Wno-pedantic -Wno-switch-outside-range" }
+
+void f(char c)
+{
+  switch (c)
+  
+    case -300 ... 300:; // { dg-bogus "lower value in case label range less than minimum value for type|upper value in case label range exceeds maximum value for type" }
+}
Marek Polacek June 20, 2019, 6:42 p.m. | #6
On Thu, Jun 20, 2019 at 09:33:18AM -0400, Matthew Beliveau wrote:
> Sorry for the last update, I guess I didn't notice the other changes, oops!

> 

> This should have all the changes. Let me know if anything went wrong!

> 

> Thanks,

> Matthew Beliveau

> 

> On Tue, Jun 18, 2019 at 1:38 PM Marek Polacek <polacek@redhat.com> wrote:

> >

> > On Tue, Jun 18, 2019 at 01:17:10PM -0400, Matthew Beliveau wrote:

> > > Hello,

> > >

> > > This patch should change the formatting, and move the test files into

> > > the appropriate directory!

> >

> > It doesn't address my other comments, though, so please send a new version

> > with that fixed.

> >

> > Marek


> Bootstrapped/regtested on x86_64-linux, ok for trunk?

> 

> 2019-06-20  Matthew Beliveau  <mbelivea@redhat.com>

> 

> 	PR c++/90875 - added -Wswitch-outside-range option

> 	* doc/invoke.texi (Wswitch-outside-range): Document.

> 

> 	* c-warn.c (c_do_switch_warnings): Implemented new Wswitch-outside-range

> 	warning option.

> 

> 	* c.opt (Wswitch-outside-range): Added new option.

> 	

> 	* c-c++-common/Wswitch-outside-range-1.C: New test.

> 	* c-c++-common/Wswitch-outside-range-2.C: New test.

> 	* c-c++-common/Wswitch-outside-range-3.C: New test.

> 	* c-c++-common/Wswitch-outside-range-4.C: New test.

> 

> diff --git gcc/c-family/c-warn.c gcc/c-family/c-warn.c

> index 5941c10cddb..743099c75ca 100644

> --- gcc/c-family/c-warn.c

> +++ gcc/c-family/c-warn.c

> @@ -1460,8 +1460,9 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location,

>  				       min_value) >= 0)

>  	    {

>  	      location_t loc = EXPR_LOCATION ((tree) node->value);

> -	      warning_at (loc, 0, "lower value in case label range"

> -				  " less than minimum value for type");

> +	      warning_at (loc, OPT_Wswitch_outside_range,

> +		     "lower value in case label range less than minimum value"

> +		     " for type");

>  	      CASE_LOW ((tree) node->value) = convert (TREE_TYPE (cond),

>  						       min_value);

>  	      node->key = (splay_tree_key) CASE_LOW ((tree) node->value);

> @@ -1474,8 +1475,8 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location,

>  	      if (node == NULL || !node->key)

>  		break;

>  	      location_t loc = EXPR_LOCATION ((tree) node->value);

> -	      warning_at (loc, 0, "case label value is less than minimum "

> -				  "value for type");

> +	      warning_at (loc, OPT_Wswitch_outside_range, "case label value is"

> +				  " less than minimum value for type");

>  	      splay_tree_remove (cases, node->key);

>  	    }

>  	  while (1);

> @@ -1491,8 +1492,8 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location,

>  				   max_value) > 0)

>  	{

>  	  location_t loc = EXPR_LOCATION ((tree) node->value);

> -	  warning_at (loc, 0, "upper value in case label range"

> -			      " exceeds maximum value for type");

> +	  warning_at (loc, OPT_Wswitch_outside_range, "upper value in case"

> +			      " label range exceeds maximum value for type");

>  	  CASE_HIGH ((tree) node->value)

>  	    = convert (TREE_TYPE (cond), max_value);

>  	  outside_range_p = true;


The formatting is still wrong here...

> @@ -1503,7 +1504,7 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location,

>  	     != NULL)

>  	{

>  	  location_t loc = EXPR_LOCATION ((tree) node->value);

> -	  warning_at (loc, 0,

> +	  warning_at (loc, OPT_Wswitch_outside_range,

>  		      "case label value exceeds maximum value for type");

>  	  splay_tree_remove (cases, node->key);

>  	  outside_range_p = true;


...but is correct here.  So make the other cases above like this one.

> diff --git gcc/doc/invoke.texi gcc/doc/invoke.texi

> index eaef4cd63d2..210535cb84a 100644

> --- gcc/doc/invoke.texi

> +++ gcc/doc/invoke.texi

> @@ -5390,6 +5390,13 @@ switch ((int) (a == 4))

>  @end smallexample

>  This warning is enabled by default for C and C++ programs.

>  

> +@item -Wswitch-outside-range

> +@opindex Wswitch-outside-range

> +@opindex Wno-switch-outside-range

> +Warn whenever a @code{switch} state has a value that is outside of its


s/state/case/

> +respective type range.  This warning is enabled by default for

> +C and C++ progarams.


"programs"

> diff --git gcc/testsuite/c-c++-common/Wswitch-outside-range-1.C gcc/testsuite/c-c++-common/Wswitch-outside-range-1.C

> new file mode 100644

> index 00000000000..29e56f3ba2d

> --- /dev/null

> +++ gcc/testsuite/c-c++-common/Wswitch-outside-range-1.C

> @@ -0,0 +1,8 @@

> +// PR c++/90875

> +

> +void f(char c)

> +{

> +  switch (c)

> +    case 300: // { dg-warning "case label value exceeds maximum value for type" }

> +    case -300:; // { dg-warning "case label value is less than minimum value for type" }

> +}

> diff --git gcc/testsuite/c-c++-common/Wswitch-outside-range-2.C gcc/testsuite/c-c++-common/Wswitch-outside-range-2.C

> new file mode 100644

> index 00000000000..20cc019b209

> --- /dev/null

> +++ gcc/testsuite/c-c++-common/Wswitch-outside-range-2.C

> @@ -0,0 +1,9 @@

> +// PR c++/90875

> +// { dg-options -Wno-switch-outside-range }

> +

> +void f(char c)

> +{

> +  switch (c)

> +    case 300: //{ dg-bogus "case label value is less than minimum value for type" }

> +    case -300:; // { dg-bogus "case label value is less than minimum value for type" }

> +}

> diff --git gcc/testsuite/c-c++-common/Wswitch-outside-range-3.C gcc/testsuite/c-c++-common/Wswitch-outside-range-3.C

> new file mode 100644

> index 00000000000..baf15561af0

> --- /dev/null

> +++ gcc/testsuite/c-c++-common/Wswitch-outside-range-3.C

> @@ -0,0 +1,9 @@

> +// PR c++/90875

> +// { dg-options -Wno-pedantic }

> +

> +void f(char c)

> +{

> +  switch (c)

> +  

> +    case -300 ... 300:; // { dg-warning "lower value in case label range less than minimum value for type|upper value in case label range exceeds maximum value for type" }

> +}

> diff --git gcc/testsuite/c-c++-common/Wswitch-outside-range-4.C gcc/testsuite/c-c++-common/Wswitch-outside-range-4.C

> new file mode 100644

> index 00000000000..d9bd756dc50

> --- /dev/null

> +++ gcc/testsuite/c-c++-common/Wswitch-outside-range-4.C

> @@ -0,0 +1,9 @@

> +// PR c++/90875

> +// { dg-options "-Wno-pedantic -Wno-switch-outside-range" }

> +

> +void f(char c)

> +{

> +  switch (c)

> +  

> +    case -300 ... 300:; // { dg-bogus "lower value in case label range less than minimum value for type|upper value in case label range exceeds maximum value for type" }

> +}


In c-c++-common/, the tests have to have file name suffix ".c", otherwise
they will be disregarded; testsuite/g++.dg/dg.exp has

# C/C++ common tests.
g++-dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/*.\[cSi\]]] \
        "" ""

Marek
Matthew Beliveau June 20, 2019, 8:26 p.m. | #7
Hopefully fixed!

On Thu, Jun 20, 2019 at 2:42 PM Marek Polacek <polacek@redhat.com> wrote:
>

> On Thu, Jun 20, 2019 at 09:33:18AM -0400, Matthew Beliveau wrote:

> > Sorry for the last update, I guess I didn't notice the other changes, oops!

> >

> > This should have all the changes. Let me know if anything went wrong!

> >

> > Thanks,

> > Matthew Beliveau

> >

> > On Tue, Jun 18, 2019 at 1:38 PM Marek Polacek <polacek@redhat.com> wrote:

> > >

> > > On Tue, Jun 18, 2019 at 01:17:10PM -0400, Matthew Beliveau wrote:

> > > > Hello,

> > > >

> > > > This patch should change the formatting, and move the test files into

> > > > the appropriate directory!

> > >

> > > It doesn't address my other comments, though, so please send a new version

> > > with that fixed.

> > >

> > > Marek

>

> > Bootstrapped/regtested on x86_64-linux, ok for trunk?

> >

> > 2019-06-20  Matthew Beliveau  <mbelivea@redhat.com>

> >

> >       PR c++/90875 - added -Wswitch-outside-range option

> >       * doc/invoke.texi (Wswitch-outside-range): Document.

> >

> >       * c-warn.c (c_do_switch_warnings): Implemented new Wswitch-outside-range

> >       warning option.

> >

> >       * c.opt (Wswitch-outside-range): Added new option.

> >

> >       * c-c++-common/Wswitch-outside-range-1.C: New test.

> >       * c-c++-common/Wswitch-outside-range-2.C: New test.

> >       * c-c++-common/Wswitch-outside-range-3.C: New test.

> >       * c-c++-common/Wswitch-outside-range-4.C: New test.

> >

> > diff --git gcc/c-family/c-warn.c gcc/c-family/c-warn.c

> > index 5941c10cddb..743099c75ca 100644

> > --- gcc/c-family/c-warn.c

> > +++ gcc/c-family/c-warn.c

> > @@ -1460,8 +1460,9 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location,

> >                                      min_value) >= 0)

> >           {

> >             location_t loc = EXPR_LOCATION ((tree) node->value);

> > -           warning_at (loc, 0, "lower value in case label range"

> > -                               " less than minimum value for type");

> > +           warning_at (loc, OPT_Wswitch_outside_range,

> > +                  "lower value in case label range less than minimum value"

> > +                  " for type");

> >             CASE_LOW ((tree) node->value) = convert (TREE_TYPE (cond),

> >                                                      min_value);

> >             node->key = (splay_tree_key) CASE_LOW ((tree) node->value);

> > @@ -1474,8 +1475,8 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location,

> >             if (node == NULL || !node->key)

> >               break;

> >             location_t loc = EXPR_LOCATION ((tree) node->value);

> > -           warning_at (loc, 0, "case label value is less than minimum "

> > -                               "value for type");

> > +           warning_at (loc, OPT_Wswitch_outside_range, "case label value is"

> > +                               " less than minimum value for type");

> >             splay_tree_remove (cases, node->key);

> >           }

> >         while (1);

> > @@ -1491,8 +1492,8 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location,

> >                                  max_value) > 0)

> >       {

> >         location_t loc = EXPR_LOCATION ((tree) node->value);

> > -       warning_at (loc, 0, "upper value in case label range"

> > -                           " exceeds maximum value for type");

> > +       warning_at (loc, OPT_Wswitch_outside_range, "upper value in case"

> > +                           " label range exceeds maximum value for type");

> >         CASE_HIGH ((tree) node->value)

> >           = convert (TREE_TYPE (cond), max_value);

> >         outside_range_p = true;

>

> The formatting is still wrong here...

>

> > @@ -1503,7 +1504,7 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location,

> >            != NULL)

> >       {

> >         location_t loc = EXPR_LOCATION ((tree) node->value);

> > -       warning_at (loc, 0,

> > +       warning_at (loc, OPT_Wswitch_outside_range,

> >                     "case label value exceeds maximum value for type");

> >         splay_tree_remove (cases, node->key);

> >         outside_range_p = true;

>

> ...but is correct here.  So make the other cases above like this one.

>

> > diff --git gcc/doc/invoke.texi gcc/doc/invoke.texi

> > index eaef4cd63d2..210535cb84a 100644

> > --- gcc/doc/invoke.texi

> > +++ gcc/doc/invoke.texi

> > @@ -5390,6 +5390,13 @@ switch ((int) (a == 4))

> >  @end smallexample

> >  This warning is enabled by default for C and C++ programs.

> >

> > +@item -Wswitch-outside-range

> > +@opindex Wswitch-outside-range

> > +@opindex Wno-switch-outside-range

> > +Warn whenever a @code{switch} state has a value that is outside of its

>

> s/state/case/

>

> > +respective type range.  This warning is enabled by default for

> > +C and C++ progarams.

>

> "programs"

>

> > diff --git gcc/testsuite/c-c++-common/Wswitch-outside-range-1.C gcc/testsuite/c-c++-common/Wswitch-outside-range-1.C

> > new file mode 100644

> > index 00000000000..29e56f3ba2d

> > --- /dev/null

> > +++ gcc/testsuite/c-c++-common/Wswitch-outside-range-1.C

> > @@ -0,0 +1,8 @@

> > +// PR c++/90875

> > +

> > +void f(char c)

> > +{

> > +  switch (c)

> > +    case 300: // { dg-warning "case label value exceeds maximum value for type" }

> > +    case -300:; // { dg-warning "case label value is less than minimum value for type" }

> > +}

> > diff --git gcc/testsuite/c-c++-common/Wswitch-outside-range-2.C gcc/testsuite/c-c++-common/Wswitch-outside-range-2.C

> > new file mode 100644

> > index 00000000000..20cc019b209

> > --- /dev/null

> > +++ gcc/testsuite/c-c++-common/Wswitch-outside-range-2.C

> > @@ -0,0 +1,9 @@

> > +// PR c++/90875

> > +// { dg-options -Wno-switch-outside-range }

> > +

> > +void f(char c)

> > +{

> > +  switch (c)

> > +    case 300: //{ dg-bogus "case label value is less than minimum value for type" }

> > +    case -300:; // { dg-bogus "case label value is less than minimum value for type" }

> > +}

> > diff --git gcc/testsuite/c-c++-common/Wswitch-outside-range-3.C gcc/testsuite/c-c++-common/Wswitch-outside-range-3.C

> > new file mode 100644

> > index 00000000000..baf15561af0

> > --- /dev/null

> > +++ gcc/testsuite/c-c++-common/Wswitch-outside-range-3.C

> > @@ -0,0 +1,9 @@

> > +// PR c++/90875

> > +// { dg-options -Wno-pedantic }

> > +

> > +void f(char c)

> > +{

> > +  switch (c)

> > +

> > +    case -300 ... 300:; // { dg-warning "lower value in case label range less than minimum value for type|upper value in case label range exceeds maximum value for type" }

> > +}

> > diff --git gcc/testsuite/c-c++-common/Wswitch-outside-range-4.C gcc/testsuite/c-c++-common/Wswitch-outside-range-4.C

> > new file mode 100644

> > index 00000000000..d9bd756dc50

> > --- /dev/null

> > +++ gcc/testsuite/c-c++-common/Wswitch-outside-range-4.C

> > @@ -0,0 +1,9 @@

> > +// PR c++/90875

> > +// { dg-options "-Wno-pedantic -Wno-switch-outside-range" }

> > +

> > +void f(char c)

> > +{

> > +  switch (c)

> > +

> > +    case -300 ... 300:; // { dg-bogus "lower value in case label range less than minimum value for type|upper value in case label range exceeds maximum value for type" }

> > +}

>

> In c-c++-common/, the tests have to have file name suffix ".c", otherwise

> they will be disregarded; testsuite/g++.dg/dg.exp has

>

> # C/C++ common tests.

> g++-dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/*.\[cSi\]]] \

>         "" ""

>

> Marek
Bootstrapped/regtested on x86_64-linux, ok for trunk?

2019-06-20  Matthew Beliveau  <mbelivea@redhat.com>

	PR c++/90875 - added -Wswitch-outside-range option
	* doc/invoke.texi (Wswitch-outside-range): Document.

	* c-warn.c (c_do_switch_warnings): Implemented new Wswitch-outside-range
	warning option.

	* c.opt (Wswitch-outside-range): Added new option.
	* c-c++-common/Wswitch-outside-range-1.c: New test.
	* c-c++-common/Wswitch-outside-range-2.c: New test.
	* c-c++-common/Wswitch-outside-range-3.c: New test.
	* c-c++-common/Wswitch-outside-range-4.c: New test.

diff --git gcc/c-family/c-warn.c gcc/c-family/c-warn.c
index 5941c10cddb..fd2f927a853 100644
--- gcc/c-family/c-warn.c
+++ gcc/c-family/c-warn.c
@@ -1460,8 +1460,9 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location,
 				       min_value) >= 0)
 	    {
 	      location_t loc = EXPR_LOCATION ((tree) node->value);
-	      warning_at (loc, 0, "lower value in case label range"
-				  " less than minimum value for type");
+	      warning_at (loc, OPT_Wswitch_outside_range,
+		     "lower value in case label range less than minimum value"
+		     " for type");
 	      CASE_LOW ((tree) node->value) = convert (TREE_TYPE (cond),
 						       min_value);
 	      node->key = (splay_tree_key) CASE_LOW ((tree) node->value);
@@ -1474,8 +1475,8 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location,
 	      if (node == NULL || !node->key)
 		break;
 	      location_t loc = EXPR_LOCATION ((tree) node->value);
-	      warning_at (loc, 0, "case label value is less than minimum "
-				  "value for type");
+	      warning_at (loc, OPT_Wswitch_outside_range, "case label value is"
+		     " less than minimum value for type");
 	      splay_tree_remove (cases, node->key);
 	    }
 	  while (1);
@@ -1491,8 +1492,8 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location,
 				   max_value) > 0)
 	{
 	  location_t loc = EXPR_LOCATION ((tree) node->value);
-	  warning_at (loc, 0, "upper value in case label range"
-			      " exceeds maximum value for type");
+	  warning_at (loc, OPT_Wswitch_outside_range, "upper value in case"
+		 " label range exceeds maximum value for type");
 	  CASE_HIGH ((tree) node->value)
 	    = convert (TREE_TYPE (cond), max_value);
 	  outside_range_p = true;
@@ -1503,7 +1504,7 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location,
 	     != NULL)
 	{
 	  location_t loc = EXPR_LOCATION ((tree) node->value);
-	  warning_at (loc, 0,
+	  warning_at (loc, OPT_Wswitch_outside_range,
 		 "case label value exceeds maximum value for type");
 	  splay_tree_remove (cases, node->key);
 	  outside_range_p = true;
diff --git gcc/c-family/c.opt gcc/c-family/c.opt
index 572cf186262..a4cf3bd623d 100644
--- gcc/c-family/c.opt
+++ gcc/c-family/c.opt
@@ -819,6 +819,10 @@ Wswitch-bool
 C ObjC C++ ObjC++ Var(warn_switch_bool) Warning Init(1)
 Warn about switches with boolean controlling expression.
 
+Wswitch-outside-range
+C ObjC C++ ObjC++ Var(warn_switch_outside_range) Warning Init(1)
+Warn about switch values that are outside of the switch's type range.
+
 Wtemplates
 C++ ObjC++ Var(warn_templates) Warning
 Warn on primary template declaration.
diff --git gcc/doc/invoke.texi gcc/doc/invoke.texi
index eaef4cd63d2..095cb18d3f8 100644
--- gcc/doc/invoke.texi
+++ gcc/doc/invoke.texi
@@ -5390,6 +5390,13 @@ switch ((int) (a == 4))
 @end smallexample
 This warning is enabled by default for C and C++ programs.
 
+@item -Wswitch-outside-range
+@opindex Wswitch-outside-range
+@opindex Wno-switch-outside-range
+Warn whenever a @code{switch} case has a value that is outside of its
+respective type range.  This warning is enabled by default for
+C and C++ programs.
+
 @item -Wswitch-unreachable
 @opindex Wswitch-unreachable
 @opindex Wno-switch-unreachable
diff --git gcc/testsuite/c-c++-common/Wswitch-outside-range-1.c gcc/testsuite/c-c++-common/Wswitch-outside-range-1.c
new file mode 100644
index 00000000000..29e56f3ba2d
--- /dev/null
+++ gcc/testsuite/c-c++-common/Wswitch-outside-range-1.c
@@ -0,0 +1,8 @@
+// PR c++/90875
+
+void f(char c)
+{
+  switch (c)
+    case 300: // { dg-warning "case label value exceeds maximum value for type" }
+    case -300:; // { dg-warning "case label value is less than minimum value for type" }
+}
diff --git gcc/testsuite/c-c++-common/Wswitch-outside-range-2.c gcc/testsuite/c-c++-common/Wswitch-outside-range-2.c
new file mode 100644
index 00000000000..20cc019b209
--- /dev/null
+++ gcc/testsuite/c-c++-common/Wswitch-outside-range-2.c
@@ -0,0 +1,9 @@
+// PR c++/90875
+// { dg-options -Wno-switch-outside-range }
+
+void f(char c)
+{
+  switch (c)
+    case 300: //{ dg-bogus "case label value is less than minimum value for type" }
+    case -300:; // { dg-bogus "case label value is less than minimum value for type" }
+}
diff --git gcc/testsuite/c-c++-common/Wswitch-outside-range-3.c gcc/testsuite/c-c++-common/Wswitch-outside-range-3.c
new file mode 100644
index 00000000000..baf15561af0
--- /dev/null
+++ gcc/testsuite/c-c++-common/Wswitch-outside-range-3.c
@@ -0,0 +1,9 @@
+// PR c++/90875
+// { dg-options -Wno-pedantic }
+
+void f(char c)
+{
+  switch (c)
+  
+    case -300 ... 300:; // { dg-warning "lower value in case label range less than minimum value for type|upper value in case label range exceeds maximum value for type" }
+}
diff --git gcc/testsuite/c-c++-common/Wswitch-outside-range-4.c gcc/testsuite/c-c++-common/Wswitch-outside-range-4.c
new file mode 100644
index 00000000000..d9bd756dc50
--- /dev/null
+++ gcc/testsuite/c-c++-common/Wswitch-outside-range-4.c
@@ -0,0 +1,9 @@
+// PR c++/90875
+// { dg-options "-Wno-pedantic -Wno-switch-outside-range" }
+
+void f(char c)
+{
+  switch (c)
+  
+    case -300 ... 300:; // { dg-bogus "lower value in case label range less than minimum value for type|upper value in case label range exceeds maximum value for type" }
+}
Matthew Beliveau June 20, 2019, 9:24 p.m. | #8
Sorry, the last version had some problems.

On Thu, Jun 20, 2019 at 4:26 PM Matthew Beliveau <mbelivea@redhat.com> wrote:
>

> Hopefully fixed!

>

> On Thu, Jun 20, 2019 at 2:42 PM Marek Polacek <polacek@redhat.com> wrote:

> >

> > On Thu, Jun 20, 2019 at 09:33:18AM -0400, Matthew Beliveau wrote:

> > > Sorry for the last update, I guess I didn't notice the other changes, oops!

> > >

> > > This should have all the changes. Let me know if anything went wrong!

> > >

> > > Thanks,

> > > Matthew Beliveau

> > >

> > > On Tue, Jun 18, 2019 at 1:38 PM Marek Polacek <polacek@redhat.com> wrote:

> > > >

> > > > On Tue, Jun 18, 2019 at 01:17:10PM -0400, Matthew Beliveau wrote:

> > > > > Hello,

> > > > >

> > > > > This patch should change the formatting, and move the test files into

> > > > > the appropriate directory!

> > > >

> > > > It doesn't address my other comments, though, so please send a new version

> > > > with that fixed.

> > > >

> > > > Marek

> >

> > > Bootstrapped/regtested on x86_64-linux, ok for trunk?

> > >

> > > 2019-06-20  Matthew Beliveau  <mbelivea@redhat.com>

> > >

> > >       PR c++/90875 - added -Wswitch-outside-range option

> > >       * doc/invoke.texi (Wswitch-outside-range): Document.

> > >

> > >       * c-warn.c (c_do_switch_warnings): Implemented new Wswitch-outside-range

> > >       warning option.

> > >

> > >       * c.opt (Wswitch-outside-range): Added new option.

> > >

> > >       * c-c++-common/Wswitch-outside-range-1.C: New test.

> > >       * c-c++-common/Wswitch-outside-range-2.C: New test.

> > >       * c-c++-common/Wswitch-outside-range-3.C: New test.

> > >       * c-c++-common/Wswitch-outside-range-4.C: New test.

> > >

> > > diff --git gcc/c-family/c-warn.c gcc/c-family/c-warn.c

> > > index 5941c10cddb..743099c75ca 100644

> > > --- gcc/c-family/c-warn.c

> > > +++ gcc/c-family/c-warn.c

> > > @@ -1460,8 +1460,9 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location,

> > >                                      min_value) >= 0)

> > >           {

> > >             location_t loc = EXPR_LOCATION ((tree) node->value);

> > > -           warning_at (loc, 0, "lower value in case label range"

> > > -                               " less than minimum value for type");

> > > +           warning_at (loc, OPT_Wswitch_outside_range,

> > > +                  "lower value in case label range less than minimum value"

> > > +                  " for type");

> > >             CASE_LOW ((tree) node->value) = convert (TREE_TYPE (cond),

> > >                                                      min_value);

> > >             node->key = (splay_tree_key) CASE_LOW ((tree) node->value);

> > > @@ -1474,8 +1475,8 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location,

> > >             if (node == NULL || !node->key)

> > >               break;

> > >             location_t loc = EXPR_LOCATION ((tree) node->value);

> > > -           warning_at (loc, 0, "case label value is less than minimum "

> > > -                               "value for type");

> > > +           warning_at (loc, OPT_Wswitch_outside_range, "case label value is"

> > > +                               " less than minimum value for type");

> > >             splay_tree_remove (cases, node->key);

> > >           }

> > >         while (1);

> > > @@ -1491,8 +1492,8 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location,

> > >                                  max_value) > 0)

> > >       {

> > >         location_t loc = EXPR_LOCATION ((tree) node->value);

> > > -       warning_at (loc, 0, "upper value in case label range"

> > > -                           " exceeds maximum value for type");

> > > +       warning_at (loc, OPT_Wswitch_outside_range, "upper value in case"

> > > +                           " label range exceeds maximum value for type");

> > >         CASE_HIGH ((tree) node->value)

> > >           = convert (TREE_TYPE (cond), max_value);

> > >         outside_range_p = true;

> >

> > The formatting is still wrong here...

> >

> > > @@ -1503,7 +1504,7 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location,

> > >            != NULL)

> > >       {

> > >         location_t loc = EXPR_LOCATION ((tree) node->value);

> > > -       warning_at (loc, 0,

> > > +       warning_at (loc, OPT_Wswitch_outside_range,

> > >                     "case label value exceeds maximum value for type");

> > >         splay_tree_remove (cases, node->key);

> > >         outside_range_p = true;

> >

> > ...but is correct here.  So make the other cases above like this one.

> >

> > > diff --git gcc/doc/invoke.texi gcc/doc/invoke.texi

> > > index eaef4cd63d2..210535cb84a 100644

> > > --- gcc/doc/invoke.texi

> > > +++ gcc/doc/invoke.texi

> > > @@ -5390,6 +5390,13 @@ switch ((int) (a == 4))

> > >  @end smallexample

> > >  This warning is enabled by default for C and C++ programs.

> > >

> > > +@item -Wswitch-outside-range

> > > +@opindex Wswitch-outside-range

> > > +@opindex Wno-switch-outside-range

> > > +Warn whenever a @code{switch} state has a value that is outside of its

> >

> > s/state/case/

> >

> > > +respective type range.  This warning is enabled by default for

> > > +C and C++ progarams.

> >

> > "programs"

> >

> > > diff --git gcc/testsuite/c-c++-common/Wswitch-outside-range-1.C gcc/testsuite/c-c++-common/Wswitch-outside-range-1.C

> > > new file mode 100644

> > > index 00000000000..29e56f3ba2d

> > > --- /dev/null

> > > +++ gcc/testsuite/c-c++-common/Wswitch-outside-range-1.C

> > > @@ -0,0 +1,8 @@

> > > +// PR c++/90875

> > > +

> > > +void f(char c)

> > > +{

> > > +  switch (c)

> > > +    case 300: // { dg-warning "case label value exceeds maximum value for type" }

> > > +    case -300:; // { dg-warning "case label value is less than minimum value for type" }

> > > +}

> > > diff --git gcc/testsuite/c-c++-common/Wswitch-outside-range-2.C gcc/testsuite/c-c++-common/Wswitch-outside-range-2.C

> > > new file mode 100644

> > > index 00000000000..20cc019b209

> > > --- /dev/null

> > > +++ gcc/testsuite/c-c++-common/Wswitch-outside-range-2.C

> > > @@ -0,0 +1,9 @@

> > > +// PR c++/90875

> > > +// { dg-options -Wno-switch-outside-range }

> > > +

> > > +void f(char c)

> > > +{

> > > +  switch (c)

> > > +    case 300: //{ dg-bogus "case label value is less than minimum value for type" }

> > > +    case -300:; // { dg-bogus "case label value is less than minimum value for type" }

> > > +}

> > > diff --git gcc/testsuite/c-c++-common/Wswitch-outside-range-3.C gcc/testsuite/c-c++-common/Wswitch-outside-range-3.C

> > > new file mode 100644

> > > index 00000000000..baf15561af0

> > > --- /dev/null

> > > +++ gcc/testsuite/c-c++-common/Wswitch-outside-range-3.C

> > > @@ -0,0 +1,9 @@

> > > +// PR c++/90875

> > > +// { dg-options -Wno-pedantic }

> > > +

> > > +void f(char c)

> > > +{

> > > +  switch (c)

> > > +

> > > +    case -300 ... 300:; // { dg-warning "lower value in case label range less than minimum value for type|upper value in case label range exceeds maximum value for type" }

> > > +}

> > > diff --git gcc/testsuite/c-c++-common/Wswitch-outside-range-4.C gcc/testsuite/c-c++-common/Wswitch-outside-range-4.C

> > > new file mode 100644

> > > index 00000000000..d9bd756dc50

> > > --- /dev/null

> > > +++ gcc/testsuite/c-c++-common/Wswitch-outside-range-4.C

> > > @@ -0,0 +1,9 @@

> > > +// PR c++/90875

> > > +// { dg-options "-Wno-pedantic -Wno-switch-outside-range" }

> > > +

> > > +void f(char c)

> > > +{

> > > +  switch (c)

> > > +

> > > +    case -300 ... 300:; // { dg-bogus "lower value in case label range less than minimum value for type|upper value in case label range exceeds maximum value for type" }

> > > +}

> >

> > In c-c++-common/, the tests have to have file name suffix ".c", otherwise

> > they will be disregarded; testsuite/g++.dg/dg.exp has

> >

> > # C/C++ common tests.

> > g++-dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/*.\[cSi\]]] \

> >         "" ""

> >

> > Marek
Bootstrapped/regtested on x86_64-linux, ok for trunk?

2019-06-20  Matthew Beliveau  <mbelivea@redhat.com>

	PR c++/90875 - added -Wswitch-outside-range option
	* doc/invoke.texi (Wswitch-outside-range): Document.

	* c-warn.c (c_do_switch_warnings): Implemented new Wswitch-outside-range
	warning option.

	* c.opt (Wswitch-outside-range): Added new option.
	* c-c++-common/Wswitch-outside-range-1.c: New test.
	* c-c++-common/Wswitch-outside-range-2.c: New test.
	* c-c++-common/Wswitch-outside-range-3.c: New test.
	* c-c++-common/Wswitch-outside-range-4.c: New test.

diff --git gcc/c-family/c-warn.c gcc/c-family/c-warn.c
index 5941c10cddb..b5d09e761d7 100644
--- gcc/c-family/c-warn.c
+++ gcc/c-family/c-warn.c
@@ -1460,8 +1460,9 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location,
 				       min_value) >= 0)
 	    {
 	      location_t loc = EXPR_LOCATION ((tree) node->value);
-	      warning_at (loc, 0, "lower value in case label range"
-				  " less than minimum value for type");
+	      warning_at (loc, OPT_Wswitch_outside_range,
+			  "lower value in case label range less than minimum"
+			  " value for type");
 	      CASE_LOW ((tree) node->value) = convert (TREE_TYPE (cond),
 						       min_value);
 	      node->key = (splay_tree_key) CASE_LOW ((tree) node->value);
@@ -1474,8 +1475,8 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location,
 	      if (node == NULL || !node->key)
 		break;
 	      location_t loc = EXPR_LOCATION ((tree) node->value);
-	      warning_at (loc, 0, "case label value is less than minimum "
-				  "value for type");
+	      warning_at (loc, OPT_Wswitch_outside_range, "case label value is"
+			  " less than minimum value for type");
 	      splay_tree_remove (cases, node->key);
 	    }
 	  while (1);
@@ -1491,8 +1492,8 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location,
 				   max_value) > 0)
 	{
 	  location_t loc = EXPR_LOCATION ((tree) node->value);
-	  warning_at (loc, 0, "upper value in case label range"
-			      " exceeds maximum value for type");
+	  warning_at (loc, OPT_Wswitch_outside_range, "upper value in case"
+		      " label range exceeds maximum value for type");
 	  CASE_HIGH ((tree) node->value)
 	    = convert (TREE_TYPE (cond), max_value);
 	  outside_range_p = true;
@@ -1503,7 +1504,7 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location,
 	     != NULL)
 	{
 	  location_t loc = EXPR_LOCATION ((tree) node->value);
-	  warning_at (loc, 0,
+	  warning_at (loc, OPT_Wswitch_outside_range,
 		      "case label value exceeds maximum value for type");
 	  splay_tree_remove (cases, node->key);
 	  outside_range_p = true;
diff --git gcc/c-family/c.opt gcc/c-family/c.opt
index 572cf186262..a4cf3bd623d 100644
--- gcc/c-family/c.opt
+++ gcc/c-family/c.opt
@@ -819,6 +819,10 @@ Wswitch-bool
 C ObjC C++ ObjC++ Var(warn_switch_bool) Warning Init(1)
 Warn about switches with boolean controlling expression.
 
+Wswitch-outside-range
+C ObjC C++ ObjC++ Var(warn_switch_outside_range) Warning Init(1)
+Warn about switch values that are outside of the switch's type range.
+
 Wtemplates
 C++ ObjC++ Var(warn_templates) Warning
 Warn on primary template declaration.
diff --git gcc/doc/invoke.texi gcc/doc/invoke.texi
index eaef4cd63d2..210535cb84a 100644
--- gcc/doc/invoke.texi
+++ gcc/doc/invoke.texi
@@ -5390,6 +5390,13 @@ switch ((int) (a == 4))
 @end smallexample
 This warning is enabled by default for C and C++ programs.
 
+@item -Wswitch-outside-range
+@opindex Wswitch-outside-range
+@opindex Wno-switch-outside-range
+Warn whenever a @code{switch} state has a value that is outside of its
+respective type range.  This warning is enabled by default for
+C and C++ progarams.
+
 @item -Wswitch-unreachable
 @opindex Wswitch-unreachable
 @opindex Wno-switch-unreachable
diff --git gcc/testsuite/c-c++-common/Wswitch-outside-range-1.c gcc/testsuite/c-c++-common/Wswitch-outside-range-1.c
new file mode 100644
index 00000000000..29e56f3ba2d
--- /dev/null
+++ gcc/testsuite/c-c++-common/Wswitch-outside-range-1.c
@@ -0,0 +1,8 @@
+// PR c++/90875
+
+void f(char c)
+{
+  switch (c)
+    case 300: // { dg-warning "case label value exceeds maximum value for type" }
+    case -300:; // { dg-warning "case label value is less than minimum value for type" }
+}
diff --git gcc/testsuite/c-c++-common/Wswitch-outside-range-2.c gcc/testsuite/c-c++-common/Wswitch-outside-range-2.c
new file mode 100644
index 00000000000..20cc019b209
--- /dev/null
+++ gcc/testsuite/c-c++-common/Wswitch-outside-range-2.c
@@ -0,0 +1,9 @@
+// PR c++/90875
+// { dg-options -Wno-switch-outside-range }
+
+void f(char c)
+{
+  switch (c)
+    case 300: //{ dg-bogus "case label value is less than minimum value for type" }
+    case -300:; // { dg-bogus "case label value is less than minimum value for type" }
+}
diff --git gcc/testsuite/c-c++-common/Wswitch-outside-range-3.c gcc/testsuite/c-c++-common/Wswitch-outside-range-3.c
new file mode 100644
index 00000000000..baf15561af0
--- /dev/null
+++ gcc/testsuite/c-c++-common/Wswitch-outside-range-3.c
@@ -0,0 +1,9 @@
+// PR c++/90875
+// { dg-options -Wno-pedantic }
+
+void f(char c)
+{
+  switch (c)
+  
+    case -300 ... 300:; // { dg-warning "lower value in case label range less than minimum value for type|upper value in case label range exceeds maximum value for type" }
+}
diff --git gcc/testsuite/c-c++-common/Wswitch-outside-range-4.c gcc/testsuite/c-c++-common/Wswitch-outside-range-4.c
new file mode 100644
index 00000000000..d9bd756dc50
--- /dev/null
+++ gcc/testsuite/c-c++-common/Wswitch-outside-range-4.c
@@ -0,0 +1,9 @@
+// PR c++/90875
+// { dg-options "-Wno-pedantic -Wno-switch-outside-range" }
+
+void f(char c)
+{
+  switch (c)
+  
+    case -300 ... 300:; // { dg-bogus "lower value in case label range less than minimum value for type|upper value in case label range exceeds maximum value for type" }
+}
Marek Polacek June 21, 2019, 3:14 p.m. | #9
On Thu, Jun 20, 2019 at 05:24:15PM -0400, Matthew Beliveau wrote:
> Bootstrapped/regtested on x86_64-linux, ok for trunk?

> 

> 2019-06-20  Matthew Beliveau  <mbelivea@redhat.com>

> 

> 	PR c++/90875 - added -Wswitch-outside-range option

> 	* doc/invoke.texi (Wswitch-outside-range): Document.

> 

> 	* c-warn.c (c_do_switch_warnings): Implemented new Wswitch-outside-range

> 	warning option.


Here you can just say "Use OPT_Wswitch_outside_range."

> 	* c.opt (Wswitch-outside-range): Added new option.

> 	* c-c++-common/Wswitch-outside-range-1.c: New test.

> 	* c-c++-common/Wswitch-outside-range-2.c: New test.

> 	* c-c++-common/Wswitch-outside-range-3.c: New test.

> 	* c-c++-common/Wswitch-outside-range-4.c: New test.


Note that the c.opt entry will go to c-family/ChangeLog while the tests will go
to testsuite/ChangeLog.

> +@item -Wswitch-outside-range

> +@opindex Wswitch-outside-range

> +@opindex Wno-switch-outside-range

> +Warn whenever a @code{switch} state has a value that is outside of its

> +respective type range.  This warning is enabled by default for

> +C and C++ progarams.

> +


Note that the typos you had fixed crept back.

OK with those fixed.  Be careful where you put the ChangeLog entries.

Marek
Jason Merrill June 21, 2019, 7:52 p.m. | #10
On 6/17/19 1:44 PM, Marek Polacek wrote:
>> +// { dg-options "-Wno-pedantic -Wno-switch-outside-range" }

> 

> (You can also use __extension__ so that you don't need -Wno-pedantic.)


Using dg-options overrides the default -pedantic-errors, so you don't 
need __extension__ either.

If you don't mean to override the default options, use 
dg-additional-options instead.

Jason
Gerald Pfeifer Oct. 27, 2019, 7:13 a.m. | #11
On Fri, 21 Jun 2019, Marek Polacek wrote:
>> 2019-06-20  Matthew Beliveau  <mbelivea@redhat.com>

>> 

>> 	PR c++/90875 - added -Wswitch-outside-range option

>> 	* doc/invoke.texi (Wswitch-outside-range): Document.


I noticed this is not yet covered in the GCC 10 release notes at
https://gcc.gnu.org/gcc-10/changes.html .

https://gcc.gnu.org/about.html has some information how to go about
our web pages (in GIT now, the CVS era is over ;-), and I'm happy to
help if you have any questions.

Gerald
Marek Polacek Oct. 28, 2019, 12:21 p.m. | #12
On Sun, Oct 27, 2019 at 08:13:52AM +0100, Gerald Pfeifer wrote:
> On Fri, 21 Jun 2019, Marek Polacek wrote:

> >> 2019-06-20  Matthew Beliveau  <mbelivea@redhat.com>

> >> 

> >> 	PR c++/90875 - added -Wswitch-outside-range option

> >> 	* doc/invoke.texi (Wswitch-outside-range): Document.

> 

> I noticed this is not yet covered in the GCC 10 release notes at

> https://gcc.gnu.org/gcc-10/changes.html .

> 

> https://gcc.gnu.org/about.html has some information how to go about

> our web pages (in GIT now, the CVS era is over ;-), and I'm happy to

> help if you have any questions.


Note the warning isn't new, just the option.

Marek

Patch

Bootstrapped/regtested on x86_64-linux, ok for trunk?

2019-06-14  Matthew Beliveau  <mbelivea@redhat.com>
	
	PR c++/90875 - added -Wswitch-outside-range option
	* doc/invoke.texi (Wswitch-outside-range): Document.

	* c-warn.c (c_do_switch_warnings): Implemented new Wswitch-outside-range
	warning option.
	
	* c.opt (Wswitch-outside-range): Added new option.

	* g++.dg/warn/Wswitch-outside-range-1.C: New test.
	* g++.dg/warn/Wswitch-outside-range-2.C: New test.
	* g++.dg/warn/Wswitch-outside-range-3.C: New test.
	* g++.dg/warn/Wswitch-outside-range-4.C: New test.

diff --git gcc/c-family/c-warn.c gcc/c-family/c-warn.c
index 5941c10cddb..b61694af638 100644
--- gcc/c-family/c-warn.c
+++ gcc/c-family/c-warn.c
@@ -1460,8 +1460,9 @@  c_do_switch_warnings (splay_tree cases, location_t switch_location,
 				       min_value) >= 0)
 	    {
 	      location_t loc = EXPR_LOCATION ((tree) node->value);
-	      warning_at (loc, 0, "lower value in case label range"
-				  " less than minimum value for type");
+	      warning_at (loc, OPT_Wswitch_outside_range, "lower value in case"
+				  " label range less than minimum value"
+				  " for type");
 	      CASE_LOW ((tree) node->value) = convert (TREE_TYPE (cond),
 						       min_value);
 	      node->key = (splay_tree_key) CASE_LOW ((tree) node->value);
@@ -1474,8 +1475,8 @@  c_do_switch_warnings (splay_tree cases, location_t switch_location,
 	      if (node == NULL || !node->key)
 		break;
 	      location_t loc = EXPR_LOCATION ((tree) node->value);
-	      warning_at (loc, 0, "case label value is less than minimum "
-				  "value for type");
+	      warning_at (loc, OPT_Wswitch_outside_range, "case label value is"
+				  " less than minimum value for type");
 	      splay_tree_remove (cases, node->key);
 	    }
 	  while (1);
@@ -1491,8 +1492,8 @@  c_do_switch_warnings (splay_tree cases, location_t switch_location,
 				   max_value) > 0)
 	{
 	  location_t loc = EXPR_LOCATION ((tree) node->value);
-	  warning_at (loc, 0, "upper value in case label range"
-			      " exceeds maximum value for type");
+	  warning_at (loc, OPT_Wswitch_outside_range, "upper value in case"
+			      " label range exceeds maximum value for type");
 	  CASE_HIGH ((tree) node->value)
 	    = convert (TREE_TYPE (cond), max_value);
 	  outside_range_p = true;
@@ -1503,7 +1504,7 @@  c_do_switch_warnings (splay_tree cases, location_t switch_location,
 	     != NULL)
 	{
 	  location_t loc = EXPR_LOCATION ((tree) node->value);
-	  warning_at (loc, 0,
+	  warning_at (loc, OPT_Wswitch_outside_range,
 		      "case label value exceeds maximum value for type");
 	  splay_tree_remove (cases, node->key);
 	  outside_range_p = true;
diff --git gcc/c-family/c.opt gcc/c-family/c.opt
index 572cf186262..4ced767ca99 100644
--- gcc/c-family/c.opt
+++ gcc/c-family/c.opt
@@ -819,6 +819,10 @@  Wswitch-bool
 C ObjC C++ ObjC++ Var(warn_switch_bool) Warning Init(1)
 Warn about switches with boolean controlling expression.
 
+Wswitch-outside-range
+C++ ObjC++ Var(warn_switch_outside_range) Warning Init(1)
+Warn about switch values that are outside of their type's range.
+
 Wtemplates
 C++ ObjC++ Var(warn_templates) Warning
 Warn on primary template declaration.
diff --git gcc/doc/invoke.texi gcc/doc/invoke.texi
index bf9da0f0a6e..c23496b2668 100644
--- gcc/doc/invoke.texi
+++ gcc/doc/invoke.texi
@@ -5390,6 +5390,12 @@  switch ((int) (a == 4))
 @end smallexample
 This warning is enabled by default for C and C++ programs.
 
+@item -Wswitch-outside-range
+@opindex Wswitch-outside-range
+@opindex Wno-switch-outside-range
+Warn whenever a @code{switch} state has a value that is outside of it's
+respective type range.
+
 @item -Wswitch-unreachable
 @opindex Wswitch-unreachable
 @opindex Wno-switch-unreachable
diff --git gcc/testsuite/g++.dg/warn/Wswitch-outside-range-1.C gcc/testsuite/g++.dg/warn/Wswitch-outside-range-1.C
new file mode 100644
index 00000000000..29e56f3ba2d
--- /dev/null
+++ gcc/testsuite/g++.dg/warn/Wswitch-outside-range-1.C
@@ -0,0 +1,8 @@ 
+// PR c++/90875
+
+void f(char c)
+{
+  switch (c)
+    case 300: // { dg-warning "case label value exceeds maximum value for type" }
+    case -300:; // { dg-warning "case label value is less than minimum value for type" }
+}
diff --git gcc/testsuite/g++.dg/warn/Wswitch-outside-range-2.C gcc/testsuite/g++.dg/warn/Wswitch-outside-range-2.C
new file mode 100644
index 00000000000..20cc019b209
--- /dev/null
+++ gcc/testsuite/g++.dg/warn/Wswitch-outside-range-2.C
@@ -0,0 +1,9 @@ 
+// PR c++/90875
+// { dg-options -Wno-switch-outside-range }
+
+void f(char c)
+{
+  switch (c)
+    case 300: //{ dg-bogus "case label value is less than minimum value for type" }
+    case -300:; // { dg-bogus "case label value is less than minimum value for type" }
+}
diff --git gcc/testsuite/g++.dg/warn/Wswitch-outside-range-3.C gcc/testsuite/g++.dg/warn/Wswitch-outside-range-3.C
new file mode 100644
index 00000000000..baf15561af0
--- /dev/null
+++ gcc/testsuite/g++.dg/warn/Wswitch-outside-range-3.C
@@ -0,0 +1,9 @@ 
+// PR c++/90875
+// { dg-options -Wno-pedantic }
+
+void f(char c)
+{
+  switch (c)
+  
+    case -300 ... 300:; // { dg-warning "lower value in case label range less than minimum value for type|upper value in case label range exceeds maximum value for type" }
+}
diff --git gcc/testsuite/g++.dg/warn/Wswitch-outside-range-4.C gcc/testsuite/g++.dg/warn/Wswitch-outside-range-4.C
new file mode 100644
index 00000000000..d9bd756dc50
--- /dev/null
+++ gcc/testsuite/g++.dg/warn/Wswitch-outside-range-4.C
@@ -0,0 +1,9 @@ 
+// PR c++/90875
+// { dg-options "-Wno-pedantic -Wno-switch-outside-range" }
+
+void f(char c)
+{
+  switch (c)
+  
+    case -300 ... 300:; // { dg-bogus "lower value in case label range less than minimum value for type|upper value in case label range exceeds maximum value for type" }
+}