#ifdef __clang__ # define FALLTHROUGH [[fallthrough]] # define __builtin_fallthrough() (void)0 #else # define FALLTHROUGH __builtin_fallthrough () #endif void f0 (void) { // This would be an invalid [[fallthrough]] and GCC rejects it // as expected with: // error: invalid use of '__builtin_fallthrough ()' FALLTHROUGH; { // This would be invalid [[fallthrough]] but is silently accepted // by GCC. 0 ? __builtin_fallthrough () : (void)0; } { switch (0) // This is invalid with [[fallthrough]] because there's no // preceding statement within the switch statement, and no // subsequent one. Clang rejects it but GCC silently accepts // it (it issues -Wswitch-unreachable). FALLTHROUGH; } { // This is invalid but GCC gives: // warning: not preceding a label // It seems that it should give an error like in the first case // above. I suspect it's confused by the preceding switch. // Clang gives an error. FALLTHROUGH; } } void f1 (void) { { switch (0) // This also seems invalid because there is no preceding // statement and no subsequent case-labeled statement but // GCC silently accepts it (as does Clang). It seems that // GCC gets tricked by the A label. default: FALLTHROUGH; A: ; } { // Unlike the same block at the end of f0 this is an error // as it should be`. FALLTHROUGH; } } void f2 (int i) { { switch (i) { case 0: // Both of the following are invalid with [[fallthrough]] // because neither is followed by a case-labeled statement. // GCC only only rejects the second of the two. Clang // accepts both. FALLTHROUGH; FALLTHROUGH; } } } // The following function triggers an ICE. void f3 (void) { { // Invalid but without the ICE silently accepted by GCC. int i = 0; if (i) __builtin_fallthrough (); } { switch (0) __builtin_fallthrough (); } __builtin_fallthrough (); }