Added fallthrough warnings
authorRobert Pengelly <robertapengelly@hotmail.com>
Sun, 23 Aug 2026 11:43:06 +0000 (12:43 +0100)
committerRobert Pengelly <robertapengelly@hotmail.com>
Sun, 23 Aug 2026 11:43:06 +0000 (12:43 +0100)
amd64.c
i386.c
token.c

diff --git a/amd64.c b/amd64.c
index a4557312a7d79892350cc74d9635993d1233c2dd..8c03d73db109b5b446ca1af1efcbd9f43b6b7fad 100644 (file)
--- a/amd64.c
+++ b/amd64.c
@@ -96,6 +96,14 @@ static void clear_rhs_last_pointer_info (void) {
 
 }
 
+#define     MAX_FALLTHROUGH_SWITCH_DEPTH        32
+
+static int fallthrough_switch_depth = 0;
+static int fallthrough_case_active[MAX_FALLTHROUGH_SWITCH_DEPTH];
+static int fallthrough_case_has_statement[MAX_FALLTHROUGH_SWITCH_DEPTH];
+
+static int fallthrough_case_ends_control_flow[MAX_FALLTHROUGH_SWITCH_DEPTH];
+
 static int current_function_has_return_statement = 0;
 static int statement_ends_control_flow = 0;
 
@@ -9304,6 +9312,13 @@ static void parse_block (void) {
                 ensure_block_stack_allocated (block_stack_start, &block_stack_bytes, &block_stack_emitted);
             }
             
+            if (fallthrough_switch_depth > 0 && fallthrough_case_active[fallthrough_switch_depth - 1]) {
+            
+                fallthrough_case_has_statement[fallthrough_switch_depth - 1] = 1;
+                fallthrough_case_ends_control_flow[fallthrough_switch_depth - 1] = 0;
+            
+            }
+            
             continue;
         
         }
@@ -9370,7 +9385,19 @@ static void parse_block (void) {
         
         }
         
-        parse_statement ();
+        {
+        
+            enum token_kind statement_kind = tok.kind;
+            parse_statement ();
+            
+            if (fallthrough_switch_depth > 0 && statement_kind != TOK_CASE && statement_kind != TOK_DEFAULT && fallthrough_case_active[fallthrough_switch_depth - 1]) {
+            
+                fallthrough_case_has_statement[fallthrough_switch_depth - 1] = 1;
+                fallthrough_case_ends_control_flow[fallthrough_switch_depth - 1] = statement_ends_control_flow;
+            
+            }
+        
+        }
         
         if (statement_ends_control_flow) {
             block_ends_control_flow = 1;
@@ -27096,6 +27123,7 @@ static void parse_switch_statement (void) {
     long old_break_cleanup_base;
     long old_continue_cleanup_base;
     
+    int fallthrough_tracking_pushed = 0;
     int saved_ends_control_flow;
     
     FILE *saved_ofp;
@@ -27141,9 +27169,23 @@ static void parse_switch_statement (void) {
     
     }
     
+    if (fallthrough_switch_depth < MAX_FALLTHROUGH_SWITCH_DEPTH) {
+    
+        fallthrough_case_active[fallthrough_switch_depth] = 0;
+        fallthrough_case_has_statement[fallthrough_switch_depth] = 0;
+        fallthrough_case_ends_control_flow[fallthrough_switch_depth] = 0;
+        fallthrough_switch_depth++;
+        fallthrough_tracking_pushed = 1;
+    
+    }
+    
     parse_statement ();
     saved_ends_control_flow = statement_ends_control_flow;
     
+    if (fallthrough_tracking_pushed) {
+        fallthrough_switch_depth--;
+    }
+    
     if (body_tmp) {
     
         body_text = read_tmp_file_text (body_tmp);
@@ -37984,6 +38026,20 @@ static void parse_statement (void) {
         const char *case_start = tok.start;
         const char *case_caret = tok.caret;
         
+        if (fallthrough_switch_depth > 0) {
+        
+            int fall_index = fallthrough_switch_depth - 1;
+            
+            if ((state->warn & WARN_FALLTHROUGH) && fallthrough_case_active[fall_index] && fallthrough_case_has_statement[fall_index] && !fallthrough_case_ends_control_flow[fall_index]) {
+                report_line_at (get_filename (), case_line, REPORT_WARNING, case_start, case_caret, "this case may be reached by fallthrough");
+            }
+            
+            fallthrough_case_active[fall_index] = 1;
+            fallthrough_case_has_statement[fall_index] = 0;
+            fallthrough_case_ends_control_flow[fall_index] = 0;
+        
+        }
+        
         get_token ();
         
         value = const_from_current_case_expr ();
@@ -38007,6 +38063,20 @@ static void parse_statement (void) {
         const char *default_start = tok.start;
         const char *default_caret = tok.caret;
         
+        if (fallthrough_switch_depth > 0) {
+        
+            int fall_index = fallthrough_switch_depth - 1;
+            
+            if ((state->warn & WARN_FALLTHROUGH) && fallthrough_case_active[fall_index] && fallthrough_case_has_statement[fall_index] && !fallthrough_case_ends_control_flow[fall_index]) {
+                report_line_at (get_filename (), default_line, REPORT_WARNING, default_start, default_caret, "this case may be reached by fallthrough");
+            }
+            
+            fallthrough_case_active[fall_index] = 1;
+            fallthrough_case_has_statement[fall_index] = 0;
+            fallthrough_case_ends_control_flow[fall_index] = 0;
+        
+        }
+        
         get_token ();
         
         set_switch_default_label (default_line, default_start, default_caret);
diff --git a/i386.c b/i386.c
index 096d5e6c7919ec1b18e3c08185623c79143d72ff..b5f8d8e44fc8d1c1f90096324be7f8ab04430cdf 100644 (file)
--- a/i386.c
+++ b/i386.c
@@ -69,6 +69,13 @@ static void clear_rhs_last_pointer_info (void) {
 
 }
 
+#define     MAX_FALLTHROUGH_SWITCH_DEPTH        32
+
+static int fallthrough_switch_depth = 0;
+static int fallthrough_case_active[MAX_FALLTHROUGH_SWITCH_DEPTH];
+static int fallthrough_case_has_statement[MAX_FALLTHROUGH_SWITCH_DEPTH];
+static int fallthrough_case_ends_control_flow[MAX_FALLTHROUGH_SWITCH_DEPTH];
+
 static int current_function_has_return_statement = 0;
 static int statement_ends_control_flow = 0;
 
@@ -8545,6 +8552,13 @@ static void parse_block (void) {
                 ensure_block_stack_allocated (block_stack_start, &block_stack_bytes, &block_stack_emitted);
             }
             
+            if (fallthrough_switch_depth > 0 && fallthrough_case_active[fallthrough_switch_depth - 1]) {
+            
+                fallthrough_case_has_statement[fallthrough_switch_depth - 1] = 1;
+                fallthrough_case_ends_control_flow[fallthrough_switch_depth - 1] = 0;
+            
+            }
+            
             continue;
         
         }
@@ -8611,7 +8625,19 @@ static void parse_block (void) {
         
         }
         
-        parse_statement ();
+        {
+        
+            enum token_kind statement_kind = tok.kind;
+            parse_statement ();
+            
+            if (fallthrough_switch_depth > 0 && statement_kind != TOK_CASE && statement_kind != TOK_DEFAULT && fallthrough_case_active[fallthrough_switch_depth - 1]) {
+            
+                fallthrough_case_has_statement[fallthrough_switch_depth - 1] = 1;
+                fallthrough_case_ends_control_flow[fallthrough_switch_depth - 1] = statement_ends_control_flow;
+            
+            }
+        
+        }
         
         if (statement_ends_control_flow) {
             block_ends_control_flow = 1;
@@ -24222,6 +24248,7 @@ static void parse_switch_statement (void) {
     long old_break_cleanup_base;
     long old_continue_cleanup_base;
     
+    int fallthrough_tracking_pushed = 0;
     int saved_ends_control_flow;
     
     FILE *saved_ofp;
@@ -24267,9 +24294,23 @@ static void parse_switch_statement (void) {
     
     }
     
+    if (fallthrough_switch_depth < MAX_FALLTHROUGH_SWITCH_DEPTH) {
+    
+        fallthrough_case_active[fallthrough_switch_depth] = 0;
+        fallthrough_case_has_statement[fallthrough_switch_depth] = 0;
+        fallthrough_case_ends_control_flow[fallthrough_switch_depth] = 0;
+        fallthrough_switch_depth++;
+        fallthrough_tracking_pushed = 1;
+    
+    }
+    
     parse_statement ();
     saved_ends_control_flow = statement_ends_control_flow;
     
+    if (fallthrough_tracking_pushed) {
+        fallthrough_switch_depth--;
+    }
+    
     if (body_tmp) {
     
         body_text = read_tmp_file_text (body_tmp);
@@ -35432,6 +35473,20 @@ static void parse_statement (void) {
         const char *case_start = tok.start;
         const char *case_caret = tok.caret;
         
+        if (fallthrough_switch_depth > 0) {
+        
+            int fall_index = fallthrough_switch_depth - 1;
+            
+            if ((state->warn & WARN_FALLTHROUGH) && fallthrough_case_active[fall_index] && fallthrough_case_has_statement[fall_index] && !fallthrough_case_ends_control_flow[fall_index]) {
+                report_line_at (get_filename (), case_line, REPORT_WARNING, case_start, case_caret, "this case may be reached by fallthrough");
+            }
+            
+            fallthrough_case_active[fall_index] = 1;
+            fallthrough_case_has_statement[fall_index] = 0;
+            fallthrough_case_ends_control_flow[fall_index] = 0;
+        
+        }
+        
         get_token ();
         
         value = const_from_current_case_expr ();
@@ -35455,6 +35510,20 @@ static void parse_statement (void) {
         const char *default_start = tok.start;
         const char *default_caret = tok.caret;
         
+        if (fallthrough_switch_depth > 0) {
+        
+            int fall_index = fallthrough_switch_depth - 1;
+            
+            if ((state->warn & WARN_FALLTHROUGH) && fallthrough_case_active[fall_index] && fallthrough_case_has_statement[fall_index] && !fallthrough_case_ends_control_flow[fall_index]) {
+                report_line_at (get_filename (), default_line, REPORT_WARNING, default_start, default_caret, "this case may be reached by fallthrough");
+            }
+            
+            fallthrough_case_active[fall_index] = 1;
+            fallthrough_case_has_statement[fall_index] = 0;
+            fallthrough_case_ends_control_flow[fall_index] = 0;
+        
+        }
+        
         get_token ();
         
         set_switch_default_label (default_line, default_start, default_caret);
diff --git a/token.c b/token.c
index e5f01a106ca8497dc5312efa6d85be0ecca1a37d..aa0ca17972c94eabeab179402bb294daf93b4cbe 100755 (executable)
--- a/token.c
+++ b/token.c
@@ -2087,10 +2087,9 @@ void get_token (void) {
             
             if (!get_line ()) {
             
-                free ((char *) get_filename ());
-                
                 if ((history = vec_pop (&vec_history))) {
                 
+                    free ((char *) get_filename ());
                     state->ifp = history->ifp;
                     
                     new_line_number = history->new_line_number;