Search code examples
cenumsgcc-warningfail-fast-fail-early

C: how can I fail to compile when -Wswitch is off?


If I want my switch(an_enum) statement to be reported when it misses an enum case, I can turn on the -Wswitch compiler flag (on gcc).

enum E { e1, e2, e3 };

...
switch(e) {
  case e1: ...
  case e2: ...
  // NO default: checked by -Wswitch and -Werror
}

It works nicely: "error: enumeration value ‘e3’ not handled in switch [-Werror=switch]"

But now the correctness of my code depends on the compiler flags in use, which is kind of brittle.

Something like this:

switch(e) __attribute__((exhaustive))
{
  ...
}

Is there a way I can have that piece of code fail if the -Wswitch flag is off? Or temporarily switch it on within the code?


Solution

  • The reliable and portable solution is to add a default label to your switch statement. It can do:

    default:
        assert(0);
        abort();
    

    so that it fails even if assertions are inhibited — or you can do something more sensible if you prefer.

    If you're using GCC, you can use diagnostic pragmas to get the required result of turning on -Wswitch for a short scope.

    #ifdef __GNUC__
    #pragma GCC diagnostic push
    #pragma GCC diagnostic error "-Wswitch"
    #endif /* __GNUC__ */
    
    switch (e)
    {
    …
    }
    
    #ifdef __GNUC__
    #pragma GCC diagnostic pop
    #endif /* __GNUC__ */
    

    This pushes the diagnostic state, changes it to add errors as if -Wswitch is specified on the command line, compiles the switch statement, and then pops (restores) the saved diagnostic state.

    If you never use a compiler other than GCC (or perhaps Clang), you can omit the __GNUC__ tests. However, compilers on other platforms (e.g. IBM XLC 13.1.3 on AIX 7.2) complain about the GCC-specific pragmas, even though the C standard says it shouldn't. You pays your money and takes your pick.

    You can use ignore or warning instead of error to achieve other effects if you prefer.

    You might also note that the -Wswitch option is one of the warnings enabled by -Wall — and if you're compiling with GCC, you should always be using -Wall (and -Wextra and -Werror), so you should never run into problems.

    Also, the correctness of your program depends on how you wrote it (or modified it), not on the compiler options. What does depend on the compiler options is whether or not the mitsakes you've made are spotted by the compiler.