Fixed parsing of unreachable code
authorRobert Pengelly <robertapengelly@hotmail.com>
Sun, 23 Aug 2026 16:33:13 +0000 (17:33 +0100)
committerRobert Pengelly <robertapengelly@hotmail.com>
Sun, 23 Aug 2026 16:33:13 +0000 (17:33 +0100)
amd64.c
cc.h
i386.c
lib.c

diff --git a/amd64.c b/amd64.c
index 82943015598b8b91d3dc580fa799cdedf65ace8f..94897021ee2fe11094ffa6a0a6b253e31d8221f1 100644 (file)
--- 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 b30e43df5aec7a77fed0735b28e952068440b161..3243bb577d936d7615a9e6467ee677b8a0b2302a 100755 (executable)
--- 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 9e7f6c1d2a1a52b6de730d794ce5bdde0280de5a..6c7367bfd82e30ee35ee044f90f7cb919108e51f 100644 (file)
--- 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 3077aaaf7cad1c761468525017c2c02d3d253a0a..17680b48507dbd5e11f3049c103f97e75b1e2e00 100755 (executable)
--- 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);