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

@@ -271,6 +271,7 @@ void NetHackQtBind::qt_askname()
// success; handle plname[] verification below prior to returning
break;
}
FALLTHROUGH;
/*FALLTHRU*/
case -2:
// Quit
@@ -726,6 +727,7 @@ char NetHackQtBind::qt_more()
switch (ch) {
case '\0': // hypothetical
ch = '\033';
FALLTHROUGH;
/*FALLTHRU*/
case ' ':
case '\n':

View File

@@ -1556,6 +1556,7 @@ menu_get_selections(WINDOW *win, nhmenu *menu, int how)
break;
}
}
FALLTHROUGH;
/*FALLTHRU*/
default:
if (curletter > 0 && curletter < 256

View File

@@ -114,6 +114,7 @@ curses_create_main_windows(void)
case 3:
noperminv_borders = TRUE;
FALLTHROUGH;
/*FALLTHRU*/
case 1: /* On */
borders = TRUE;
@@ -121,6 +122,7 @@ curses_create_main_windows(void)
case 4:
noperminv_borders = TRUE;
FALLTHROUGH;
/*FALLTHRU*/
case 2: /* Auto */
borders = (term_cols >= 80 + 2 && term_rows >= 24 + 2);

View File

@@ -291,7 +291,7 @@ curses_break_str(const char *str, int width, int line_num)
char *retstr;
int curline = 0;
int strsize = (int) strlen(str) + 1;
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) && !defined(_MSC_VER)
char substr[strsize];
char curstr[strsize];
char tmpstr[strsize];
@@ -363,7 +363,7 @@ curses_str_remainder(const char *str, int width, int line_num)
char *retstr;
int curline = 0;
int strsize = strlen(str) + 1;
#if __STDC_VERSION__ >= 199901L
#if (__STDC_VERSION__ >= 199901L) && !defined(_MSC_VER)
char substr[strsize];
char tmpstr[strsize];
@@ -801,6 +801,7 @@ curses_convert_keys(int key)
a value for ^H greater than 255 is passed back to core's
readchar() and stripping the value down to 0..255 yields ^G! */
ret = C('H');
FALLTHROUGH;
/*FALLTHRU*/
default:
if (modifiers_available)

View File

@@ -415,6 +415,7 @@ draw_horizontal(boolean border)
w -= (t - 30); /* '+= strlen()' below will add 't';
* functional result being 'w += 30' */
}
FALLTHROUGH;
/*FALLTHRU*/
case BL_ALIGN:
case BL_LEVELDESC:
@@ -1231,6 +1232,7 @@ curs_vert_status_vals(int win_width)
if (fld_width < hp_width + 3) /* +3: " " gap and "("...")" */
Sprintf(leadingspace, "%*s",
(hp_width + 3) - fld_width, " ");
FALLTHROUGH;
/*FALLTHRU*/
case BL_VERS:
case BL_EXP:

View File

@@ -98,6 +98,7 @@ curses_create_window(int wid, int width, int height, orient orientation)
switch (orientation) {
default:
impossible("curses_create_window: Bad orientation");
FALLTHROUGH;
/*FALLTHRU*/
case CENTER:
startx = (term_cols / 2) - (width / 2);

View File

@@ -1341,6 +1341,7 @@ s_atr2str(int n)
/* if italic isn't available, fall through to underline */
if (ZH && *ZH)
return ZH;
FALLTHROUGH;
/*FALLTHRU*/
case ATR_BLINK:
case ATR_ULINE:
@@ -1351,6 +1352,7 @@ s_atr2str(int n)
if (nh_US && *nh_US)
return nh_US;
}
FALLTHROUGH;
/*FALLTHRU*/
case ATR_BOLD:
if (MD && *MD)
@@ -1378,15 +1380,18 @@ e_atr2str(int n)
/* send ZR unless we didn't have ZH and substituted US */
if (ZR && *ZR && ZH && *ZH)
return ZR;
FALLTHROUGH;
/*FALLTHRU*/
case ATR_ULINE:
if (nh_UE && *nh_UE)
return nh_UE;
FALLTHROUGH;
/*FALLTHRU*/
case ATR_BOLD:
case ATR_BLINK:
if (nh_HE && *nh_HE)
return nh_HE;
FALLTHROUGH;
/*FALLTHRU*/
case ATR_DIM:
case ATR_INVERSE:

View File

@@ -665,6 +665,7 @@ tty_askname(void)
case -1:
bail("Until next time then..."); /* quit */
/*NOTREACHED*/
break;
case 0:
break; /* no game chosen; start new game */
case 1:
@@ -1084,6 +1085,7 @@ tty_clear_nhwindow(winid window)
case NHW_MAP:
/* cheap -- clear the whole thing and tell nethack to redraw botl */
disp.botlx = TRUE;
FALLTHROUGH;
/*FALLTHRU*/
case NHW_BASE:
/* if erasing_tty_screen is True, calling sequence is
@@ -1721,6 +1723,7 @@ process_menu_window(winid window, struct WinDesc *cw)
break;
case MENU_EXPLICIT_CHOICE:
morc = really_morc;
FALLTHROUGH;
/*FALLTHRU*/
default:
if (cw->how == PICK_NONE || !strchr(resp, morc)) {
@@ -1878,12 +1881,14 @@ tty_display_nhwindow(
tty_display_nhwindow(WIN_MESSAGE, TRUE);
return;
}
FALLTHROUGH;
/*FALLTHRU*/
case NHW_BASE:
(void) fflush(stdout);
break;
case NHW_TEXT:
cw->maxcol = ttyDisplay->cols; /* force full-screen mode */
FALLTHROUGH;
/*FALLTHRU*/
case NHW_MENU:
cw->active = 1;
@@ -1951,6 +1956,7 @@ tty_dismiss_nhwindow(winid window)
if (ttyDisplay->toplin != TOPLINE_EMPTY)
tty_display_nhwindow(WIN_MESSAGE, TRUE);
nhassert(ttyDisplay->toplin == TOPLINE_EMPTY);
FALLTHROUGH;
/*FALLTHRU*/
case NHW_STATUS:
case NHW_BASE:
@@ -4438,6 +4444,7 @@ tty_status_update(
switch (fldidx) {
case BL_RESET:
reset_state = FORCE_RESET;
FALLTHROUGH;
/*FALLTHRU*/
case BL_FLUSH:
if (make_things_fit(reset_state) || truncation_expected) {
@@ -4458,6 +4465,7 @@ tty_status_update(
break;
case BL_GOLD:
text = decode_mixed(goldbuf, text);
FALLTHROUGH;
/*FALLTHRU*/
default:
attrmask = (color >> 8) & 0x00FF;
@@ -4506,6 +4514,7 @@ tty_status_update(
break;
case BL_LEVELDESC:
dlvl_shrinklvl = 0; /* caller is passing full length string */
FALLTHROUGH;
/*FALLTHRU*/
case BL_HUNGER:
/* The core sends trailing blanks for some fields.

View File

@@ -146,7 +146,8 @@ GetlinDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
(WPARAM) sizeof(wbuf2), (LPARAM) wbuf2);
NH_W2A(wbuf2, data->result, data->result_size);
/* Fall through. */
FALLTHROUGH;
/* FALLTHRU */
/* cancel button was pressed */
case IDCANCEL:
@@ -246,7 +247,8 @@ ExtCmdDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
hWnd, IDC_EXTCMD_LIST, LB_GETCURSEL, (WPARAM) 0, (LPARAM) 0);
if (*data->selection == LB_ERR)
*data->selection = -1;
/* Fall through. */
FALLTHROUGH;
/* FALLTHRU */
/* CANCEL button ws clicked */
case IDCANCEL: