-Wimplicit-fallthrough
At some point, the “big three” C/C compilers (GCC, Clang, MSVC) gained a warning about implict fallthroughs in switch
statements:
#include <stdio.h>
int main(int argc, char **argv) {
(void) argv;
switch (argc) {
case 2:
printf("2 args\n");
case 1:
printf("1 arg\n");
default:
printf("default\n");
break;
}
return 0;
}
$ gcc -Wimplicit-fallthrough fallthrough.c
fallthrough.c: In function 'main':
fallthrough.c:8:13: warning: this statement may fall through [-Wimplicit-fallthrough=]
8 | printf("2 args\n");
| ^~~~~~~~~~~~~~~~~~
fallthrough.c:9:9: note: here
9 | case 1:
| ^~~~
fallthrough.c:10:13: warning: this statement may fall through [-Wimplicit-fallthrough=]
10 | printf("1 arg\n");
| ^~~~~~~~~~~~~~~~~
fallthrough.c:11:9: note: here
11 | default:
| ^~~~~~~
This is both annoying and useful.
Annoying because I use fallthroughs intentionally a lot, useful because I also accidentally forget to add a break
a lot! So, of course, it’d be useful to indicate to the compiler somehow that the fallthrough is intentional.
The easiest solution is -Wno-implicit-fallthrough
(disable the warning), but of course I still want it for when I do mistakenly use a fallthrough.
C provides a [[fallthrough]]
attribute to explicitly indicate a fallthrough.
Awesome…
but I’m using C.
Well, C23 also provides it! Alas, a lot of projects target older C standards, C23 is new enough that there are plenty of systems out there with a compiler too old to support it, and MSVC seems to support very little of it so far.
According to the GCC docs, -Wimplicit-fallthrough
has six levels.
Wow.
Levels 1-4 list a mass of increasingly strict regular expressions it matches comments agains to guess whether a fallthrough is intentional; the default level is 3.
So, this shuts up GCC:
switch (argc) {
case 2:
printf("2 args\n");
// fallthrough
case 1:
printf("1 arg\n");
// fallthrough
default:
printf("default\n");
break;
}
But, the comment technique and varying levels for the warning are exclusive to GCC.
Clang’s implementation of the warning is just on or off, and it’ll want you to use an attribute, suggesting the GNU extension __attribute__((fallthrough))
:
$ clang -Wimplicit-fallthrough fallthrough.c
fallthrough.c:9:9: warning: unannotated fall-through between switch labels [-Wimplicit-fallthrough]
9 | case 1:
| ^
fallthrough.c:9:9: note: insert '__attribute__((fallthrough));' to silence this warning
9 | case 1:
| ^
| __attribute__((fallthrough));
fallthrough.c:9:9: note: insert 'break;' to avoid fall-through
9 | case 1:
| ^
| break;
fallthrough.c:11:9: warning: unannotated fall-through between switch labels [-Wimplicit-fallthrough]
11 | default:
| ^
fallthrough.c:11:9: note: insert '__attribute__((fallthrough));' to silence this warning
11 | default:
| ^
| __attribute__((fallthrough));
fallthrough.c:11:9: note: insert 'break;' to avoid fall-through
11 | default:
| ^
| break;
2 warnings generated.
Microsoft Visual C has also gained a similar feature, christened as the catchy Warning C26819.
Even in C I’m not sure how to enable this warning; I suspect it might be an IntelliSense warning but I couldn’t get it working in the IDE or compiler.
Either way, the only way mentioned by the docs of specifying that a fallthrough was intentional is via [[fallthrough]]
- which it doesn’t support in C mode, so if this warning is used in C, there’s no way to do it.
Agh.
So in short: if you’re using C++17 or C23, count yourself lucky and use [[fallthrough]]
.
If you’re using only GCC or Clang, use __attribute__((fallthrough))
.
Only GCC, you can use a comment.
Otherwise, I don’t know, cry?