[mcs] Detect constant switch statement fall-through. Fixes #42585
[mono.git] / mcs / mcs / statement.cs
index d0341cb3b633045c48889bfa3a3f31789df36ff0..703e7ba497fef805446a5df389a8fa4f81258816 100644 (file)
@@ -5378,18 +5378,30 @@ namespace Mono.CSharp {
                                                continue;
                                        }
 
-                                       if (constant_label != null && constant_label != sl)
+                                       if (section_rc.IsUnreachable) {
+                                               //
+                                               // Common case. Previous label section end is unreachable as
+                                               // it ends with break, return, etc. For next section revert
+                                               // to reachable again unless we have constant switch block
+                                               //
+                                               section_rc = constant_label != null && constant_label != sl ?
+                                                       Reachability.CreateUnreachable () :
+                                                       new Reachability ();
+                                       } else if (prev_label != null) {
+                                               //
+                                               // Error case as control cannot fall through from one case label
+                                               //
+                                               sl.SectionStart = false;
+                                               s = new MissingBreak (prev_label);
+                                               s.MarkReachable (rc);
+                                               block.Statements.Insert (i - 1, s);
+                                               ++i;
+                                       } else if (constant_label != null && constant_label != sl) {
+                                               //
+                                               // Special case for the first unreachable label in constant
+                                               // switch block
+                                               //
                                                section_rc = Reachability.CreateUnreachable ();
-                                       else if (section_rc.IsUnreachable) {
-                                               section_rc = new Reachability ();
-                                       } else {
-                                               if (prev_label != null) {
-                                                       sl.SectionStart = false;
-                                                       s = new MissingBreak (prev_label);
-                                                       s.MarkReachable (rc);
-                                                       block.Statements.Insert (i - 1, s);
-                                                       ++i;
-                                               }
                                        }
 
                                        prev_label = sl;