This is the mail archive of the gcc@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]

Re: enumeration value ... not handled in switch


At 2001-09-26, Joerg Faschingbauer writes:

> From: "Schirmer, Hartmut" <SchirmerH@Innovative-Systems.de>
> Subject: enumeration value ... not handled in switch
> Date: Mon, 24 Sep 2001 10:06:21 +0200
> 
> > Hi,
> > 
> > is there any way to tell GCC to warn about unhandled
> > enum values in switch-case statements even if a default
> > case is present?
> > 
> > Currently I have to do ugly things like
> > 
> >   flag = 0;
> >   switch ( e )
> >   {
> >   case e1: flag = 1; break;
> >   case e2: flag = 1; break;
> >   }
> >   if ( !flag )
> >   {
> >     // default case
> >   }
> > 
> > to get both, the default case and the warning.
> > 
> > Adding an attribute to default: would be ok in this case.
> 
> This is bug #3780. I'll be cleaning up my patch a bit (although it
> won't become less dirty by doing so :-) and submit it. (This won't
> happen before two weeks, though.)

(The original message is archived [1].)

Bug #3780 [2] doesn't seem to adress the issue brought up by Hartmut,
namely that adding a default case to a switch statement has the
sometimes-unfortunate side effect of turning off the warning about
unhandled enumeration values.

As it seems, this problem cannot be solved without adding an attribute
that declares a default case to be exceptional.

Consider the following code:

   struct fruit
   {
     enum { APPLE, MELON, ORANGE } type;
     ...
   } fruit;

   ...

   switch (fruit.type)
     {
       case APPLE:
         ...; break;
       case MELON:
         ...; break;
       case ORANGE:
         ...; break;
     }

Here, as soon as another value is added to the enum, gcc will warn
about the switch statement not handling it.

But what if `fruit_type' is neither `APPLE' nor `ORANGE'?  The fact
that this is an impossible situation implies that when it *does*
occur, the program is in an undefined state.  Thus, it should fail as
quickly and noisily as possible:

   switch (fruit.type)
     {
       case APPLE:
         ...; break;
       case MELON:
         ...; break;
       case ORANGE:
         ...; break;
       default:
         abort ();
     }

However, adding this guard prevents gcc from warning about unhandled
enumeration values.

The problem is that gcc cannot distinguish default cases intended to
detect impossible situations from those intended as catch-alls for
unspecified but valid enumeration values, such as this one:

   switch (fruit.type)
     {
       case APPLE:
         handle_apple (&fruit);
         break;
       default:
         handle_other_fruit (&fruit);
     }

Here, the impossible situations are deferred to `handle_other_fruit'.
Ideally, C would allow both kinds of default cases simultaneously when
switching on enums.  For example, why not use the `extern' keyword?

   switch (fruit.type)
     {
       case APPLE:
         handle_apple (&fruit);
         break;
       default:
         handle_other_fruit (&fruit);
         break;
       extern:
         abort ();
     }

Really, we don't want to do that, and it is not what I am proposing.
But the above syntax is simple syntactic sugar for the following:

   switch (fruit.type)
     {
       case APPLE:
         handle_apple (&fruit);
         break;
       case MELON:
       case ORANGE:
         handle_other_fruit (&fruit);
         break;
       default:
         abort ();
     }

The only missing piece here is being able to declare that the default
case is intended to handle *exceptional* cases only:

   switch (fruit.type)
     {
       case APPLE:
         handle_apple (&fruit);
         break;
       case MELON:
       case ORANGE:
         handle_other_fruit (&fruit);
         break;
       default __attribute__ ((exceptional)):
         abort ();
     }

The meaning of the `exceptional' attribute is simple:  Any default
case with this attribute does not in itself prevent warnings about
unanticipated enumeration values.

This change would stop people from being forced to artificially choose
between run-time sanity and compile-time helpfulness.


Thanks,

-- 
Daniel Brockman  <daniel@brockman.se>

[1] http://gcc.gnu.org/ml/gcc/2001-09/msg01034.html
[2] http://gcc.gnu.org/bugzilla/show_bug.cgi?id=3780


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