| // Copyright (c) 2024, the Dart project authors.  Please see the AUTHORS file | 
 | // for details. All rights reserved. Use of this source code is governed by a | 
 | // BSD-style license that can be found in the LICENSE file. | 
 |  | 
 | // Test switch statement "fallthrough" behavior. | 
 | // | 
 | // Tests behavior for Dart from version 3.0, where there is no error or | 
 | // warning related to control reaching the end of switch cases. | 
 | // See `case_fallthrough_legacy_error_test.dart` for previous behavior. | 
 |  | 
 | // Return type `dynamic` to avoid a warning for either of | 
 | // `return;` or `return x;`. | 
 | dynamic testSwitch(int x) { | 
 |   // Catch all control flow leaving the switch. | 
 |   // Run switch in catch clause to check that `rethrow` is control flow. | 
 |   TRY: | 
 |   try { | 
 |     throw x; | 
 |   } catch (_) { | 
 |     // Add loop as break/continue target. | 
 |     LOOP: | 
 |     do { | 
 |       switch (x) { | 
 |         case 0: | 
 |         case 1: | 
 |           nop(x); | 
 |           break; // Break switch. | 
 |         case 2: | 
 |           nop(x); | 
 |           break LOOP; | 
 |         case 3: | 
 |           nop(x); | 
 |           continue; // Continue loop. | 
 |         case 4: | 
 |           nop(x); | 
 |           continue LOOP; | 
 |         case 5: | 
 |           nop(x); | 
 |           continue LAST; | 
 |         case 6: | 
 |           nop(x); | 
 |           return; | 
 |         case 7: | 
 |           nop(x); | 
 |           return x; | 
 |         case 8: | 
 |           nop(x); | 
 |           throw x; | 
 |         case 9: | 
 |           nop(x); | 
 |           rethrow; | 
 |         case 10: | 
 |         case 11: | 
 |           { | 
 |             nop(x); | 
 |             break; | 
 |           } | 
 |         case 12: | 
 |           { | 
 |             nop(x); | 
 |             break LOOP; | 
 |           } | 
 |         case 13: | 
 |           { | 
 |             nop(x); | 
 |             continue; // Continue loop. | 
 |           } | 
 |         case 14: | 
 |           { | 
 |             nop(x); | 
 |             continue LOOP; | 
 |           } | 
 |         case 15: | 
 |           { | 
 |             nop(x); | 
 |             continue LAST; | 
 |           } | 
 |         case 16: | 
 |           { | 
 |             nop(x); | 
 |             return; | 
 |           } | 
 |         case 17: | 
 |           { | 
 |             nop(x); | 
 |             return x; | 
 |           } | 
 |         case 18: | 
 |           { | 
 |             nop(x); | 
 |             throw x; | 
 |           } | 
 |         case 19: | 
 |           { | 
 |             nop(x); | 
 |             rethrow; | 
 |           } | 
 |         case 20: | 
 |           { | 
 |             { | 
 |               nop(x); | 
 |               break; // Break and exit switch. | 
 |             } | 
 |           } | 
 |         case 21: | 
 |           { | 
 |             { | 
 |               nop(x); | 
 |               break LOOP; // Break loop, exits switch (and loop). | 
 |             } | 
 |           } | 
 |         case 22: | 
 |           { | 
 |             { | 
 |               nop(x); | 
 |               continue; // Continue loop, exits switch. | 
 |             } | 
 |           } | 
 |         case 23: | 
 |           { | 
 |             { | 
 |               nop(x); | 
 |               continue LOOP; // Continue loop, exits switch. | 
 |             } | 
 |           } | 
 |         case 24: | 
 |           { | 
 |             { | 
 |               nop(x); | 
 |               continue LAST; // Exits case, goto other case. | 
 |             } | 
 |           } | 
 |         case 25: | 
 |           { | 
 |             { | 
 |               nop(x); | 
 |               return; // Exits function, loop and switch. | 
 |             } | 
 |           } | 
 |         case 26: | 
 |           { | 
 |             { | 
 |               nop(x); | 
 |               return x; // Exits function, loop and switch. | 
 |             } | 
 |           } | 
 |         case 27: | 
 |           { | 
 |             { | 
 |               nop(x); | 
 |               throw x; // Exits switch. | 
 |             } | 
 |           } | 
 |         case 28: | 
 |           { | 
 |             { | 
 |               nop(x); | 
 |               rethrow; // Exits switch. | 
 |             } | 
 |           } | 
 |         case 29: | 
 |           while (true) break; // Breaks loop, reaches end. | 
 |         case 30: | 
 |           do break; while (true); // Breaks loop, reaches end. | 
 |         case 31: | 
 |           for (;;) break; // Breaks loop, reaches end. | 
 |         case 32: | 
 |           for (var _ in []) break LOOP; // Can be empty, reaches end. | 
 |         case 33: | 
 |           if (x.isEven) { | 
 |             break; // Breaks and exits switch. | 
 |           } else { | 
 |             break LOOP; // Breaks loop and exits switch. | 
 |           } | 
 |         case 34: | 
 |           (throw 0); // Exits switch. | 
 |         case 35: | 
 |           nop(x); // Reaches end. | 
 |         case 36: | 
 |           L: | 
 |           break; // Breaks and exits switch. | 
 |         case 37: | 
 |           L: | 
 |           break L; // Breaks break statement only, reaches end. | 
 |         case 38: | 
 |           L: | 
 |           if (x.isOdd) { | 
 |             break L; // Breaks if, reaches end. | 
 |           } else { | 
 |             break LOOP; | 
 |           } | 
 |         case 39: | 
 |           notEver(x); // Type Never implies not completing. | 
 |         case 40: { | 
 |           notEver(x); | 
 |         } | 
 |         case 41: { | 
 |           { | 
 |             notEver(x); | 
 |           } | 
 |         } | 
 |         case 42: { | 
 |           do { | 
 |             notEver(x); | 
 |           } while (true); | 
 |         } | 
 |         case 43: { | 
 |           if (x.isEven) { | 
 |             notEver(x); | 
 |           } else { | 
 |             notEver(-x); | 
 |           } | 
 |         } | 
 |         case 44: | 
 |           nop(x.isEven ? notEver(x) : notEver(-x)); | 
 |         LAST: | 
 |         case 99: | 
 |       } | 
 |     } while (false); | 
 |   } finally { | 
 |     // Catch all control flow leaving the switch and ignore it. | 
 |     break TRY; | 
 |   } | 
 | } | 
 |  | 
 | Never notEver(int x) { | 
 |   if (x < 0) { | 
 |     notEver(x + 1); | 
 |   } else { | 
 |     throw AssertionError("Never"); | 
 |   } | 
 | } | 
 |  | 
 | main() { | 
 |   // Don't let compiler optimize for a specific value. | 
 |   for (int i = 0; i <= 100; i++) { | 
 |     testSwitch(i); | 
 |   } | 
 | } | 
 |  | 
 | /// Don't make it obvious that a switch case isn't doing anything. | 
 | void nop(Object? x) {} |