This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH]: Don't apply default conversions to C switch expressions



>From my reading of the draft C99 rationale document, section 6.8.4.2 on
page 84 states that "case labels are first converted to the type of the
controlling expression of the switch, then checked for equality with
other labels."  I believe that in the switch statement, "switch (x)",
the type of the controlling expression is the type of x, possibly an
"unsigned char" or a enumaral type.

GNU C compiler currently calls "default_conversion" in "c_start_case"
which promotes these types to integers, which I believe is incorrect
according to the above document.  This patch removes the call to
"default_conversion" and thereby, I believe, fixes PR c/4475.  This
is a regression from 2.95.

The patch also includes two gcc.dg test cases: "Wswitch-1.c" to check
that the command line option "-Wswitch" correctly reports whether all
enumeration values are handled in switches, and "switch-2.c" that checks
whether case labels are both converted to the type of the controlling
expression and are tested for duplicates after conversion.

If the language lawyers, Joseph?, agree with my interpretation that
this is the correct thing to do and fixes c/4475, I'll be happy to
submit a similar patch for the C++ front-end to fix c++/3780.

This patch has been tested with "make bootstrap" and "make -k check"
on i686-pc-linux-gnu with no new regressions.  Unfortunately it does
produce additional warnings in the bootstrap.  I'll post a patch to
fix those I'm aware of in the next few minutes.



2001-12-09  Roger Sayle <roger@eyesopen.com>
	* c-typeck.c (c_start_case): Avoid calling default_conversion on
	the controlling expression of a C switch statement.


*** gcc/gcc/c-typeck.c	Sun Dec  9 20:19:06 2001
--- patch/gcc/c-typeck.c	Sun Dec  9 22:30:51 2001
*************** c_start_case (exp)
*** 7114,7120 ****
  	}
        else
  	{
- 	  tree index;
  	  type = TYPE_MAIN_VARIANT (TREE_TYPE (exp));

  	  if (warn_traditional && !in_system_header
--- 7114,7119 ----
*************** c_start_case (exp)
*** 7122,7137 ****
  		  || type == long_unsigned_type_node))
  	    warning ("`long' switch expression not converted to `int' in ISO C");

- 	  exp = default_conversion (exp);
  	  type = TREE_TYPE (exp);
- 	  index = get_unwidened (exp, NULL_TREE);
- 	  /* We can't strip a conversion from a signed type to an
- 	     unsigned, because if we did, int_fits_type_p would do the
- 	     wrong thing when checking case values for being in range,
- 	     and it's too hard to do the right thing.  */
- 	  if (TREE_UNSIGNED (TREE_TYPE (exp))
- 	      == TREE_UNSIGNED (TREE_TYPE (index)))
- 	    exp = index;
  	}
      }

--- 7121,7127 ----
*** /dev/null	Tue May  5 14:32:27 1998
--- switch-2.c	Mon Dec 10 09:40:20 2001
***************
*** 0 ****
--- 1,19 ----
+ /* Copyright (C) 2001 Free Software Foundation, Inc.  */
+
+ /* { dg-do compile } */
+
+ /* Source: Roger Sayle, 10 Dec 2001.  */
+
+ int
+ foo (unsigned char x)
+ {
+   switch (x)
+   {
+     case  -1: return 1;
+     case   0: return 2;  /* { dg-warning "previously used here" } */
+     case 256: return 3;  /* { dg-warning "implicitly truncated" } */
+     /* { dg-warning "duplicate case value" "" { 14 } } */
+   }
+   return 0;
+ }
+
*** /dev/null	Tue May  5 14:32:27 1998
--- Wswitch-1.c	Mon Dec 10 09:40:25 2001
***************
*** 0 ****
--- 1,46 ----
+ /* Copyright (C) 2001 Free Software Foundation, Inc.  */
+
+ /* { dg-do compile } */
+ /* { dg-options "-Wswitch -pedantic-errors" } */
+
+ /* Source: Roger Sayle, 10 Dec 2001.  */
+
+ typedef enum { red, green, blue } color;
+
+ int
+ foo (color x)
+ {
+     switch (x)
+     {
+         case red:    return 1;
+         case green:  return 2;
+         default:     break;
+     }
+     return 0;
+ }
+
+
+ int
+ bar (color x)
+ {
+     switch (x)
+     {
+         case red:    return 1;
+         case green:  return 2;
+         case blue:   return 3;
+     }
+     return 0;
+ }
+
+
+ int
+ barf (color x)
+ {
+     switch (x)
+     {
+         case red:    return 1;
+         case green:  return 2;
+     } /* { dg-warning "not handled in switch" } */
+     return 0;
+ }
+

Roger
--
Roger Sayle,                         E-mail: roger@eyesopen.com
OpenEye Scientific Software,         WWW: http://www.eyesopen.com/
Suite 1107, 3600 Cerrillos Road,     Tel: (+1) 505-473-7385
Santa Fe, New Mexico, 87507.         Fax: (+1) 505-438-3470


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]