expand implicit fallthrough detection to non-gcc compilers

gcc has recognized various "magic comments" for white-listing
occurrences of implicit fallthrough in switch statements for
a long time:

    The range and shape of "falls through" comments accepted are
    contingent upon the level of the warning. (The default level is =3.)

    -Wimplicit-fallthrough=0 disables the warning altogether.
    -Wimplicit-fallthrough=1 treats any kind of comment as a "falls through" comment.
    -Wimplicit-fallthrough=2 essentially accepts any comment that contains something
     that matches (case insensitively) "falls?[ \t-]*thr(ough|u)" regular expression.
    -Wimplicit-fallthrough=3 case sensitively matches a wide range of regular
     expressions, listed in the GCC manual. E.g., all of these are accepted:
        /* Falls through. */
        /* fall-thru */
        /* Else falls through. */
        /* FALLTHRU */
        /* ... falls through ... */
       etc.
    -Wimplicit-fallthrough=4 also, case sensitively matches a range of regular
     expressions but is much more strict than level =3.
    -Wimplicit-fallthrough=5 doesn't recognize any comments.

Plenty of other compilers did not recognize the gcc comment convention,
and up until now the compiler warning for detecting unintended
fallthrough had to be suppressed on other compilers. That's because the code
in NetHack has been relying on the gcc approach, and only the gcc approach.

The C23 standard introduces an attribute [[fallthrough]] for the
functionality, when implicit fallthrough warnings have been enabled.

Several popular compilers already support that, or a very similar attribute
style approach, today, even ahead of their C23 support:

       C compiler                       whitelist approach
       ---------------------------   -------------------------------------
       C23 conforming compilers         [[fallthrough]]

       clang versions supporting
       standards prior to
       C23                              __attribute__((__fallthrough__))

       Microsoft Visual Studio
       since VS 2022 17.4.
       The warning C5262 controls
       whether the implict
       fallthrough is detected and
       warned about with
       /std:clatest.                    [[fallthrough]]

This adds support to NetHack for the attribute approach by inserting a
macro FALLTHROUGH to the existing cases that require white-listing, so
other compilers can analyze things too.

The definition of the FALLTHROUGH macro is controlled in include/tradstdc.h.

The gcc comment approach has also been left in place at this time.
This commit is contained in:
nhmall
2024-11-30 14:16:27 -05:00
parent d6beba7b6a
commit 0792e5fe9e
73 changed files with 287 additions and 32 deletions

View File

@@ -293,6 +293,7 @@ term_end_attr(int attr)
switch (attr) {
case ATR_INVERSE:
inversed = 0;
FALLTHROUGH;
/*FALLTHRU*/
case ATR_ULINE:
case ATR_BOLD:
@@ -341,6 +342,7 @@ term_start_attr(int attr)
break;
case ATR_INVERSE:
inversed = 1;
FALLTHROUGH;
/*FALLTHRU*/
default:
g_attribute = iflags.grmode ? attrib_gr_normal : attrib_text_normal;

View File

@@ -78,20 +78,29 @@ CXX=g++ -std=gnu++11
GCCGTEQ9 := $(shell expr `$(CC) -dumpversion | cut -f1 -d.` \>= 9)
GCCGTEQ11 := $(shell expr `$(CC) -dumpversion | cut -f1 -d.` \>= 11)
GCCGTEQ12 := $(shell expr `$(CC) -dumpversion | cut -f1 -d.` \>= 12)
GCCGTEQ14 := $(shell expr `$(CC) -dumpversion | cut -f1 -d.` \>= 14)
ifeq "$(GCCGTEQ9)" "1"
# flags present in gcc version greater than or equal to 9 can go here
CFLAGS+=-Wformat-overflow
CFLAGS+=-Wmissing-parameter-type
endif # GCC greater than or equal to 9
#ifeq "$(GCCGTEQ11)" "1"
CFLAGS+=-Wimplicit-fallthrough
#endif
#ifeq "$(GCCGTEQ12)" "1"
#endif
#ifeq "$(GCCGTEQ14)" "1"
CFLAGS+=-std=gnu23
#endif
# end of gcc-specific
else # gcc or clang?
CXX=clang++ -std=gnu++11
# clang-specific follows
CLANGGTEQ12 := $(shell expr `$(CC) -dumpversion | cut -f1 -d.` \>= 12)
CLANGGTEQ14 := $(shell expr `$(CC) -dumpversion | cut -f1 -d.` \>= 14)
ifeq "$(CLANGGTEQ12)" "1"
CFLAGS+=-Wimplicit-fallthrough
endif
ifeq "$(CLANGGTEQ14)" "1"
ifneq "$(VIEWDEPRECATIONS)" "1"
CFLAGS+=-Wno-deprecated-declarations

View File

@@ -142,6 +142,7 @@ MSDOS_TARGET_CFLAGS = -c -O -I../include -I../sys/msdos -I../win/share \
-Wall -Wextra -Wno-missing-field-initializers -Wreturn-type -Wunused \
-Wformat -Wswitch -Wshadow -Wwrite-strings \
-Wimplicit -Wimplicit-function-declaration -Wimplicit-int \
-Wimplicit-fallthrough \
-Wmissing-parameter-type -Wold-style-definition -Wstrict-prototypes
MSDOS_TARGET_CXXFLAGS = -c -O -I../include -I../sys/msdos -I../win/share \
$(LUAINCL) -DDLB $(PDCURSESDEF) \

View File

@@ -241,6 +241,7 @@ vms_define(const char *name, const char *value, int flag)
switch (flag) {
case ENV_JOB: /* job logical name */
tbl_dsc.len = strlen(tbl_dsc.adr = "LNM$JOB");
FALLTHROUGH;
/*FALLTHRU*/
case ENV_SUP: /* supervisor-mode process logical name */
result = lib$set_logical(&nam_dsc, &val_dsc, &tbl_dsc);

View File

@@ -1131,10 +1131,18 @@ scall =
# 4777 format string requires an argument of type 'type',
# but variadic argument 'position' has type 'type'
# 4820 padding in struct
# 5262 enable fallthrough warnings that lack [[fallthrough]]
#
ctmpflags = $(ctmpflags:-W3=-W4) -wd4100 -wd4244 -wd4245 -wd4310 -wd4706 -w44777 -wd4820
!IF ($(VSVER) >= 2019)
ctmpflags = $(ctmpflags) -w44774
!ENDIF
!IF ($(VSVER) >= 2022)
!IF ($(MAKEVERSION) >= 1440338120)
# warning 5262 became available starting in Visual Studio 2022 version 17.4.
ctmpflags = $(ctmpflags) -w45262 /std:clatest
!ENDIF
!ENDIF
!ENDIF
#More verbose warning output options below
@@ -2880,6 +2888,8 @@ $(OTTY)sfstruct.o: sfstruct.c $(HACK_H)
$(OTTY)shk.o: shk.c $(HACK_H)
$(OTTY)shknam.o: shknam.c $(HACK_H)
$(OTTY)sit.o: sit.c $(HACK_H) $(INCL)\artifact.h
$(Q)$(CC) $(CFLAGS) /EP $(@B).c > $(OTTY)$(@B).c.preproc
$(Q)$(CC) $(CFLAGS) -Fo$@ $(@B).c
$(OTTY)sounds.o: sounds.c $(HACK_H)
$(OTTY)sp_lev.o: sp_lev.c $(HACK_H) $(INCL)\sp_lev.h
$(OTTY)spell.o: spell.c $(HACK_H)

View File

@@ -1087,6 +1087,7 @@ CtrlHandler(DWORD ctrltype)
/* case CTRL_C_EVENT: */
case CTRL_BREAK_EVENT:
term_clear_screen();
FALLTHROUGH;
case CTRL_CLOSE_EVENT:
case CTRL_LOGOFF_EVENT:
case CTRL_SHUTDOWN_EVENT:
@@ -1335,7 +1336,8 @@ xputc_core(int ch)
case '\n':
if (console.cursor.Y < console.height - 1)
console.cursor.Y++;
/* fall through */
FALLTHROUGH;
/* FALLTHRU */
case '\r':
console.cursor.X = 1;
break;
@@ -1879,6 +1881,7 @@ toggle_mouse_support(void)
#endif /* VIRTUAL_TERMINAL_SEQUENCES */
break;
case 0:
FALLTHROUGH;
/*FALLTHRU*/
default:
#ifndef VIRTUAL_TERMINAL_SEQUENCES

View File

@@ -630,7 +630,7 @@ process_options(int argc, char * argv[])
break;
} else
raw_printf("\nUnknown switch: %s", argv[0]);
/* FALL THROUGH */
FALLTHROUGH;
case '?':
nhusage();
nethack_exit(EXIT_SUCCESS);