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

@@ -403,7 +403,8 @@ fix_worst_trouble(int trouble)
break;
case TROUBLE_STARVING:
/* temporarily lost strength recovery now handled by init_uhunger() */
/*FALLTHRU*/
FALLTHROUGH;
/* FALLTHRU*/
case TROUBLE_HUNGRY:
Your("%s feels content.", body_part(STOMACH));
init_uhunger();
@@ -745,7 +746,9 @@ angrygods(aligntyp resp_god)
gods_angry(resp_god);
punish((struct obj *) 0);
break;
} /* else fall thru */
}
FALLTHROUGH;
/* FALLTHRU */
case 4:
case 5:
gods_angry(resp_god);
@@ -1127,6 +1130,7 @@ pleased(aligntyp g_align)
switch (min(action, 5)) {
case 5:
pat_on_head = 1;
FALLTHROUGH;
/*FALLTHRU*/
case 4:
do
@@ -1137,8 +1141,9 @@ pleased(aligntyp g_align)
case 3:
/* up to 10 troubles */
fix_worst_trouble(trouble);
FALLTHROUGH;
/*FALLTHRU*/
case 2:
case 2:
/* up to 9 troubles */
while ((trouble = in_trouble()) > 0 && (++tryct < 10))
fix_worst_trouble(trouble);
@@ -1234,6 +1239,7 @@ pleased(aligntyp g_align)
break;
}
}
FALLTHROUGH;
/*FALLTHRU*/
case 2:
if (!Blind)
@@ -1335,6 +1341,7 @@ pleased(aligntyp g_align)
gcrownu();
break;
}
FALLTHROUGH;
/*FALLTHRU*/
case 6:
give_spell();
@@ -2335,18 +2342,23 @@ maybe_turn_mon_iter(struct monst *mtmp)
than zombies. */
case S_LICH:
xlev += 2;
FALLTHROUGH;
/*FALLTHRU*/
case S_GHOST:
xlev += 2;
FALLTHROUGH;
/*FALLTHRU*/
case S_VAMPIRE:
xlev += 2;
FALLTHROUGH;
/*FALLTHRU*/
case S_WRAITH:
xlev += 2;
FALLTHROUGH;
/*FALLTHRU*/
case S_MUMMY:
xlev += 2;
FALLTHROUGH;
/*FALLTHRU*/
case S_ZOMBIE:
if (u.ulevel >= xlev && !resist(mtmp, '\0', 0, NOTELL)) {
@@ -2358,6 +2370,7 @@ maybe_turn_mon_iter(struct monst *mtmp)
}
break;
} /* else flee */
FALLTHROUGH;
/*FALLTHRU*/
default:
monflee(mtmp, 0, FALSE, TRUE);
@@ -2656,6 +2669,7 @@ blocked_boulder(int dx, int dy)
/* this is only approximate since multiple boulders might sink */
if (is_pool_or_lava(nx, ny)) /* does its own isok() check */
break; /* still need Sokoban check below */
FALLTHROUGH;
/*FALLTHRU*/
default:
/* more than one boulder--blocked after they push the top one;