From 90b0789bf6270980f4a9180b7bdb3067d9997c52 Mon Sep 17 00:00:00 2001 From: Robert Pengelly Date: Sun, 23 Aug 2026 17:33:13 +0100 Subject: [PATCH] Fixed parsing of unreachable code --- amd64.c | 18 +++++++++++++++++- cc.h | 2 +- i386.c | 18 +++++++++++++++++- lib.c | 8 ++++++++ 4 files changed, 43 insertions(+), 3 deletions(-) diff --git a/amd64.c b/amd64.c index 8294301..9489702 100644 --- a/amd64.c +++ b/amd64.c @@ -37498,10 +37498,26 @@ static int parse_parenthesized_member_function_pointer_call_statement (void) { static void parse_statement_suppressed (void) { FILE *save_ofp = state->ofp; + FILE *discard_ofp = 0; - state->ofp = 0; + /* + * Suppressed statements still need to go through the normal expression + * parser. Several expression paths use state->ofp == 0 as a special + * parsing mode, so simply clearing the output stream can make otherwise + * valid dead code fail to parse (for example `return (rc);` after an + * infinite loop). Emit into a temporary stream instead and discard it. + */ + if (save_ofp) { + discard_ofp = scc_tmpfile (); + } + + state->ofp = discard_ofp; parse_statement (); state->ofp = save_ofp; + + if (discard_ofp) { + scc_close (discard_ofp); + } } diff --git a/cc.h b/cc.h index b30e43d..3243bb5 100755 --- a/cc.h +++ b/cc.h @@ -22,7 +22,7 @@ #define WARN_OLD_STYLE (1U << 9) #define WARN_INITIALIZER (1U << 10) -#define WARN_DEFAULT (WARN_DUP_DEFINE | WARN_UNREACHABLE) +#define WARN_DEFAULT (WARN_DUP_DEFINE) #define WARN_ALL (WARN_DEFAULT | WARN_NO_RETURN | WARN_SIGNEDNESS | WARN_UNUSED | WARN_FALLTHROUGH | WARN_INITIALIZER) #define WARN_EXTRA (WARN_ALL | WARN_CONVERSION | WARN_OLD_STYLE) diff --git a/i386.c b/i386.c index 9e7f6c1..6c7367b 100644 --- a/i386.c +++ b/i386.c @@ -34969,10 +34969,26 @@ static int parse_parenthesized_member_function_pointer_call_statement (void) { static void parse_statement_suppressed (void) { FILE *save_ofp = state->ofp; + FILE *discard_ofp = 0; - state->ofp = 0; + /* + * Suppressed statements still need to go through the normal expression + * parser. Several expression paths use state->ofp == 0 as a special + * parsing mode, so simply clearing the output stream can make otherwise + * valid dead code fail to parse (for example `return (rc);` after an + * infinite loop). Emit into a temporary stream instead and discard it. + */ + if (save_ofp) { + discard_ofp = scc_tmpfile (); + } + + state->ofp = discard_ofp; parse_statement (); state->ofp = save_ofp; + + if (discard_ofp) { + scc_close (discard_ofp); + } } diff --git a/lib.c b/lib.c index 3077aaa..17680b4 100755 --- a/lib.c +++ b/lib.c @@ -145,6 +145,7 @@ static void print_usage (void) { fprintf (stderr, " -Werror Treat all warnings as errors.\n"); fprintf (stderr, " -Wextra Print extra (possibly unwanted) warnings.\n"); fprintf (stderr, " -Wshadow Warn when one variable shadows another.\n"); + fprintf (stderr, " -Wunreachable-code Warn about code that will never be executed.\n"); fprintf (stderr, "\n"); fprintf (stderr, " --traditional-linemarker-format Use #line instead of short form.\n"); @@ -580,6 +581,13 @@ void parse_args (int argc, char **argv, int optind) { } + if (strcmp (optarg, "unreachable-code") == 0) { + + state->warn |= WARN_UNREACHABLE; + break; + + } + report_at (program_name, 0, REPORT_ERROR, "unrecognised -W argument"); exit (EXIT_FAILURE); -- 2.34.1