8

Let's have a list of values (foo.lst):

foo,
bar,
baz,

Let's make an enum out of this

enum foo {
  #include "foo.lst"
  _foo_length
};

Let's use that enum in a switch:

int main(void) {
  enum foo[_foo_length];

  switch(f[0]) {
    case foo: return 0;
    case bar: return 0;
    case baz: return 0;
  }

  __builtin_unreachable();
}

(this code is dumb, but just ignore that)

The problem:
With -Wswitch (included in -Wall), GCC and Clang (and probably others) will warn:

warning: enumeration value '_foo_length' not handled in switch [-Wswitch]

Solutions:

  • Disabling -Wno-switch hides that warning.
    Downside: we lose warnings about any other case missing from the switch.
  • Adding a default: unreachable(); case.
    Downside: we lose compile-time warnings of missing cases, in favour of a runtime crash if we ever hit one of the missing cases when debugging.
  • Replacing the last value of the enum with a #define _foo_length (baz + 1), making it not part of the enum anymore.
    Downside: it requires that define to be manually updated every time a value is added to the list. Someone will invariably forget, breaking everything.

Ideally, there should be a way to mark an enum's value as no being assignable, thereby making it not produce a warning in the compiler when reading the possible values and this one isn't there, without requiring a preprocessor macro needing duplicate modifications.

Is there anything like that? Any other option I didn't think of?

1ace
  • 5,272
  • 4
  • 23
  • 30
  • Since you're creating the enum dynamically, how can you be sure that the `switch` really covers all the cases? – Barmar Aug 26 '16 at 16:38
  • And what happens if the file doesn't have one of the cases? This whole thing smells wrong to me. – Barmar Aug 26 '16 at 16:39
  • 2
    You can add a `case _foo_length:` – Barmar Aug 26 '16 at 16:39
  • @Barmar - (To your first comment) Isn't that exactly the rationale behind `-Wswitch`? – Oliver Charlesworth Aug 26 '16 at 16:39
  • 1
    @OliverCharlesworth `-Wswitch` performs the opposite test. If `foo.lst` is missing one of the names, he'll get an undefined variable error. But I wonder why he would hard-code names in a `switch` when he's loading the names dynamically, there seems to be a design error there. – Barmar Aug 26 '16 at 16:41
  • AFAIK there is no gcc switch that can say: `don't warn me if I didn't include XXX in the switch but I want to be warned for all other enum values` – Support Ukraine Aug 26 '16 at 16:41
  • I'm not sure this will help but maybe it could be of interest: http://stackoverflow.com/q/3378560/4386427 – Support Ukraine Aug 26 '16 at 16:45
  • @Barmar: OliverCharlesworth is right, the whole point of -Wswitch is to warn if a case listed in the file but not handled in one of the switches. The opposite case wouldn't happen in my situation, but if it did, it would just result in a compile error (unknown symbol). – 1ace Aug 28 '16 at 13:45
  • And yes @Barmar, `case _foo_length: break;` is a good solution I hadn't though of, although a bit verbose (has to be in each and every `switch`). Post this as an answer and I'll accept it :) – 1ace Aug 28 '16 at 13:47

1 Answers1

3

Use

case _foo_length:
    unreachable();
    break;

so that all the cases will be handled. You could create a macro for it to keep it from being so verbose.

Barmar
  • 741,623
  • 53
  • 500
  • 612