aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2024-09-04 18:31:28 -0700
committerGitHub <noreply@github.com>2024-09-04 18:31:28 -0700
commit3929cac154d71a3e19fd028fc67c1d1d15823ca2 (patch)
tree3ab01ff8d25313b57bbb485e30a09bc9947448f7 /test
parent7e31804870cac14063b2468f544fc77a4cbb616f (diff)
parent289c704b60c3e4b65bc00be55266b3f1c3fc27a3 (diff)
downloadzig-3929cac154d71a3e19fd028fc67c1d1d15823ca2.tar.gz
zig-3929cac154d71a3e19fd028fc67c1d1d15823ca2.zip
Merge pull request #21257 from mlugg/computed-goto-3
compiler: implement labeled switch/continue
Diffstat (limited to 'test')
-rw-r--r--test/behavior.zig1
-rw-r--r--test/behavior/switch.zig24
-rw-r--r--test/behavior/switch_loop.zig200
-rw-r--r--test/cases/compile_errors/duplicate-unused_labels.zig6
4 files changed, 231 insertions, 0 deletions
diff --git a/test/behavior.zig b/test/behavior.zig
index eca6cee5af..f0d05a146a 100644
--- a/test/behavior.zig
+++ b/test/behavior.zig
@@ -89,6 +89,7 @@ test {
_ = @import("behavior/struct_contains_null_ptr_itself.zig");
_ = @import("behavior/struct_contains_slice_of_itself.zig");
_ = @import("behavior/switch.zig");
+ _ = @import("behavior/switch_loop.zig");
_ = @import("behavior/switch_prong_err_enum.zig");
_ = @import("behavior/switch_prong_implicit_cast.zig");
_ = @import("behavior/switch_on_captured_error.zig");
diff --git a/test/behavior/switch.zig b/test/behavior/switch.zig
index 1cec0dfad4..f1ded573a0 100644
--- a/test/behavior/switch.zig
+++ b/test/behavior/switch.zig
@@ -961,3 +961,27 @@ test "block error return trace index is reset between prongs" {
};
try result;
}
+
+test "labeled switch with break" {
+ var six: u32 = undefined;
+ six = 6;
+
+ const val = s: switch (six) {
+ 0...4 => break :s false,
+ 5 => break :s false,
+ 6...7 => break :s true,
+ else => break :s false,
+ };
+
+ try expect(val);
+
+ // Make sure the switch is implicitly comptime!
+ const comptime_val = s: switch (@as(u32, 6)) {
+ 0...4 => break :s false,
+ 5 => break :s false,
+ 6...7 => break :s true,
+ else => break :s false,
+ };
+
+ comptime assert(comptime_val);
+}
diff --git a/test/behavior/switch_loop.zig b/test/behavior/switch_loop.zig
new file mode 100644
index 0000000000..d35a4e1636
--- /dev/null
+++ b/test/behavior/switch_loop.zig
@@ -0,0 +1,200 @@
+const builtin = @import("builtin");
+const std = @import("std");
+const expect = std.testing.expect;
+
+test "simple switch loop" {
+ if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
+
+ const S = struct {
+ fn doTheTest() !void {
+ var start: u32 = undefined;
+ start = 32;
+ const result: u32 = s: switch (start) {
+ 0 => 0,
+ 1 => 1,
+ 2 => 2,
+ 3 => 3,
+ else => |x| continue :s x / 2,
+ };
+ try expect(result == 2);
+ }
+ };
+ try S.doTheTest();
+ try comptime S.doTheTest();
+}
+
+test "switch loop with ranges" {
+ if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
+
+ const S = struct {
+ fn doTheTest() !void {
+ var start: u32 = undefined;
+ start = 32;
+ const result = s: switch (start) {
+ 0...3 => |x| x,
+ else => |x| continue :s x / 2,
+ };
+ try expect(result == 2);
+ }
+ };
+ try S.doTheTest();
+ try comptime S.doTheTest();
+}
+
+test "switch loop on enum" {
+ if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
+
+ const S = struct {
+ const E = enum { a, b, c };
+
+ fn doTheTest() !void {
+ var start: E = undefined;
+ start = .a;
+ const result: u32 = s: switch (start) {
+ .a => continue :s .b,
+ .b => continue :s .c,
+ .c => 123,
+ };
+ try expect(result == 123);
+ }
+ };
+ try S.doTheTest();
+ try comptime S.doTheTest();
+}
+
+test "switch loop on tagged union" {
+ if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
+
+ const S = struct {
+ const U = union(enum) {
+ a: u32,
+ b: f32,
+ c: f32,
+ };
+
+ fn doTheTest() !void {
+ var start: U = undefined;
+ start = .{ .a = 80 };
+ const result = s: switch (start) {
+ .a => |x| switch (x) {
+ 0...49 => continue :s .{ .b = @floatFromInt(x) },
+ 50 => continue :s .{ .c = @floatFromInt(x) },
+ else => continue :s .{ .a = x / 2 },
+ },
+ .b => |x| x,
+ .c => return error.TestFailed,
+ };
+ try expect(result == 40.0);
+ }
+ };
+ try S.doTheTest();
+ try comptime S.doTheTest();
+}
+
+test "switch loop dispatching instructions" {
+ if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
+
+ const S = struct {
+ const Inst = union(enum) {
+ set: u32,
+ add: u32,
+ sub: u32,
+ end,
+ };
+
+ fn doTheTest() !void {
+ var insts: [5]Inst = undefined;
+ @memcpy(&insts, &[5]Inst{
+ .{ .set = 123 },
+ .{ .add = 100 },
+ .{ .sub = 50 },
+ .{ .sub = 10 },
+ .end,
+ });
+ var i: u32 = 0;
+ var cur: u32 = undefined;
+ eval: switch (insts[0]) {
+ .set => |x| {
+ cur = x;
+ i += 1;
+ continue :eval insts[i];
+ },
+ .add => |x| {
+ cur += x;
+ i += 1;
+ continue :eval insts[i];
+ },
+ .sub => |x| {
+ cur -= x;
+ i += 1;
+ continue :eval insts[i];
+ },
+ .end => {},
+ }
+ try expect(cur == 163);
+ }
+ };
+ try S.doTheTest();
+ try comptime S.doTheTest();
+}
+
+test "switch loop with pointer capture" {
+ if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
+
+ const S = struct {
+ const U = union(enum) {
+ a: u32,
+ b: u32,
+ c: u32,
+ };
+
+ fn doTheTest() !void {
+ var a: U = .{ .a = 100 };
+ var b: U = .{ .b = 200 };
+ var c: U = .{ .c = 300 };
+ inc: switch (a) {
+ .a => |*x| {
+ x.* += 1;
+ continue :inc b;
+ },
+ .b => |*x| {
+ x.* += 10;
+ continue :inc c;
+ },
+ .c => |*x| {
+ x.* += 50;
+ },
+ }
+ try expect(a.a == 101);
+ try expect(b.b == 210);
+ try expect(c.c == 350);
+ }
+ };
+ try S.doTheTest();
+ try comptime S.doTheTest();
+}
diff --git a/test/cases/compile_errors/duplicate-unused_labels.zig b/test/cases/compile_errors/duplicate-unused_labels.zig
index 301d273bde..7b22edef20 100644
--- a/test/cases/compile_errors/duplicate-unused_labels.zig
+++ b/test/cases/compile_errors/duplicate-unused_labels.zig
@@ -22,6 +22,11 @@ comptime {
comptime {
blk: for (@as([0]void, undefined)) |_| {}
}
+comptime {
+ blk: switch (true) {
+ else => {},
+ }
+}
// error
// target=native
@@ -35,3 +40,4 @@ comptime {
// :17:5: error: unused block label
// :20:5: error: unused while loop label
// :23:5: error: unused for loop label
+// :26:5: error: unused switch label