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

[Bug c/61864] Feature Request, -Wcovered-switch-default to identify "dead" default branch


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61864

--- Comment #4 from Eric Gallager <egall at gwmail dot gwu.edu> ---
Actually, after giving this some more thought, and reading the GCC
documentation some more, I came up with some ideas for a compromise that could
allow both -Wswitch-default and -Wcovered-switch-default to be used without
conflicting:

* Seeing as -Wcovered-switch-default (as clang implements it) makes certain
assumptions about the nature of enums, its implementation in GCC should be
restricted to only being active when the -fstrict-enums flag is also in use. As
-fstrict-enums is a C++-only flag, this would effectively make
-Wcovered-switch-default a C++-only warning, which would allow C-only
programmers (such as myself) to avoid the flag.
* Besides general philosophical issues with the -Wcovered-switch-default flag,
there's also two specific implementation issues I have with clang's
implementation of it that I would want to see GCC fix in its own
implementation. I wrote a quick source file to demonstrate:

$ cat switches.c
#include <stdlib.h> /* for rand() */
int main(void)
{
    int swindex0 = rand();
    enum values {
        FIRST_ENUMERATOR,
        SECOND_ENUMERATOR,
        THIRD_ENUMERATOR
    } swindex1 = SECOND_ENUMERATOR; /* silence unitialized warnings */
    /* do the non-enumerator switch first: */
    switch (swindex0) {
        case 1:
            swindex1 = FIRST_ENUMERATOR;
            break;
        case 2:
            swindex1 = SECOND_ENUMERATOR;
            break;
        case 3:
            swindex1 = THIRD_ENUMERATOR;
            break;
        /* -Wswitch-default: usual warning about switch with no default */
    }
    if (swindex0 > 3) {
        swindex1 = THIRD_ENUMERATOR;
    } else if (swindex0 < 1) {
        swindex1 = FIRST_ENUMERATOR;
    }

    switch (swindex1) {
        case FIRST_ENUMERATOR:
            break;
        case SECOND_ENUMERATOR:
            break;
        case THIRD_ENUMERATOR:
            break;
        /* -Wcovered-switch-default: print a warning here like clang's,
         * but only if also used with -fstrict-enums: */
        default:
            break;
    }
    switch (swindex1) {
        case FIRST_ENUMERATOR:
            break;
        case SECOND_ENUMERATOR:
            break;
        case THIRD_ENUMERATOR:
            break;
        /* -Wswitch-default: still warns:
         * * if by itself, the usual message, as in the first switch.
         * * if with -Wcovered-switch-default, use a different message,
         *   like:
         *   "Warning: switch missing default case which would be covered if it
had one"
         *   "Note: use -fstrict-enums to silence this warning"
         * * if with -fstrict-enums, do like mentioned in the previous,
         *   and print no warning. */
    }
    switch (swindex1) {
        case FIRST_ENUMERATOR:
            break;
        case SECOND_ENUMERATOR:
            break;
        case THIRD_ENUMERATOR:
            break;
        /* Ideally there should be no warning here whatsoever; clang still
         * warns about it though: */
        default: __builtin_unreachable(); /*NOTREACHED*/
    }
    switch (swindex1) {
        case FIRST_ENUMERATOR:
            break;
        case SECOND_ENUMERATOR:
            break;
        case THIRD_ENUMERATOR: /*FALLTHROUGH*/
        /* Ideally there should be no warning from -Wcovered-switch-default
         * here, because even though there are labels for all enum values,
         * the 3rd case still falls through to the default case: */
        default: /*REACHEDBYFALLTHROUGH*/
            break;
        /* (clang still warns here though) */
    }
}

$ clang --version && clang -c -Weverything switches.c
clang version 3.6.0 (tags/RELEASE_360/final)
Target: x86_64-apple-darwin10.8.0
Thread model: posix
switches.c:38:9: warning: default label in switch which covers all enumeration
values [-Wcovered-switch-default]
        default:
        ^
switches.c:66:9: warning: default label in switch which covers all enumeration
values [-Wcovered-switch-default]
        default: __builtin_unreachable(); /*NOTREACHED*/
        ^
switches.c:77:9: warning: default label in switch which covers all enumeration
values [-Wcovered-switch-default]
        default: /*REACHEDBYFALLTHROUGH*/
        ^
3 warnings generated.


$ g++-6_git --version && g++-6_git -c -fstrict-enums -Wall -Wextra -Wswitch
-Wswitch-default -Wswitch-enum switches.c
g++-6_git (GCC) 6.0.0 20150604 (experimental)
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

switches.c: In function 'int main()':
switches.c:11:12: warning: switch missing default case [-Wswitch-default]
     switch (swindex0) {
            ^
switches.c:41:12: warning: switch missing default case [-Wswitch-default]
     switch (swindex1) {
            ^

I'll add the file as an attachment, too.


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