c9d54c12f6
Change-Id: I3c5cfbc1bc5e41d2ef1598427067dea00f9f42b4 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/425403 Reviewed-by: Lasse Nielsen <lrn@google.com> Commit-Queue: Lasse Nielsen <lrn@google.com> Auto-Submit: Bob Nystrom <rnystrom@google.com>
247 lines
5.3 KiB
Dart
247 lines
5.3 KiB
Dart
// 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) {}
|