master
1const builtin = @import("builtin");
2const std = @import("std");
3const expect = std.testing.expect;
4
5test "simple switch loop" {
6 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
7 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
8 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
9 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
10
11 const S = struct {
12 fn doTheTest() !void {
13 var start: u32 = undefined;
14 start = 32;
15 const result: u32 = s: switch (start) {
16 0 => 0,
17 1 => 1,
18 2 => 2,
19 3 => 3,
20 else => |x| continue :s x / 2,
21 };
22 try expect(result == 2);
23 }
24 };
25 try S.doTheTest();
26 try comptime S.doTheTest();
27}
28
29test "switch loop with ranges" {
30 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
31 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
32 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
33 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
34
35 const S = struct {
36 fn doTheTest() !void {
37 var start: u32 = undefined;
38 start = 32;
39 const result = s: switch (start) {
40 0...3 => |x| x,
41 else => |x| continue :s x / 2,
42 };
43 try expect(result == 2);
44 }
45 };
46 try S.doTheTest();
47 try comptime S.doTheTest();
48}
49
50test "switch loop on enum" {
51 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
52 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
53 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
54 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
55
56 const S = struct {
57 const E = enum { a, b, c };
58
59 fn doTheTest() !void {
60 var start: E = undefined;
61 start = .a;
62 const result: u32 = s: switch (start) {
63 .a => continue :s .b,
64 .b => continue :s .c,
65 .c => 123,
66 };
67 try expect(result == 123);
68 }
69 };
70 try S.doTheTest();
71 try comptime S.doTheTest();
72}
73
74test "switch loop with error set" {
75 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
76 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
77 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
78 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
79
80 const S = struct {
81 const E = error{ Foo, Bar, Baz };
82
83 fn doTheTest() !void {
84 var start: E = undefined;
85 start = error.Foo;
86 const result: u32 = s: switch (start) {
87 error.Foo => continue :s error.Bar,
88 error.Bar => continue :s error.Baz,
89 error.Baz => 123,
90 };
91 try expect(result == 123);
92 }
93 };
94 try S.doTheTest();
95 try comptime S.doTheTest();
96}
97
98test "switch loop on tagged union" {
99 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
100 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
101 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
102 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
103 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
104
105 const S = struct {
106 const U = union(enum) {
107 a: u32,
108 b: f32,
109 c: f32,
110 };
111
112 fn doTheTest() !void {
113 var start: U = undefined;
114 start = .{ .a = 80 };
115 const result = s: switch (start) {
116 .a => |x| switch (x) {
117 0...49 => continue :s .{ .b = @floatFromInt(x) },
118 50 => continue :s .{ .c = @floatFromInt(x) },
119 else => continue :s .{ .a = x / 2 },
120 },
121 .b => |x| x,
122 .c => return error.TestFailed,
123 };
124 try expect(result == 40.0);
125 }
126 };
127 try S.doTheTest();
128 try comptime S.doTheTest();
129}
130
131test "switch loop dispatching instructions" {
132 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
133 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
134 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
135 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
136
137 const S = struct {
138 const Inst = union(enum) {
139 set: u32,
140 add: u32,
141 sub: u32,
142 end,
143 };
144
145 fn doTheTest() !void {
146 var insts: [5]Inst = undefined;
147 @memcpy(&insts, &[5]Inst{
148 .{ .set = 123 },
149 .{ .add = 100 },
150 .{ .sub = 50 },
151 .{ .sub = 10 },
152 .end,
153 });
154 var i: u32 = 0;
155 var cur: u32 = undefined;
156 eval: switch (insts[0]) {
157 .set => |x| {
158 cur = x;
159 i += 1;
160 continue :eval insts[i];
161 },
162 .add => |x| {
163 cur += x;
164 i += 1;
165 continue :eval insts[i];
166 },
167 .sub => |x| {
168 cur -= x;
169 i += 1;
170 continue :eval insts[i];
171 },
172 .end => {},
173 }
174 try expect(cur == 163);
175 }
176 };
177 try S.doTheTest();
178 try comptime S.doTheTest();
179}
180
181test "switch loop with pointer capture" {
182 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
183 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
184 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
185 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
186
187 const S = struct {
188 const U = union(enum) {
189 a: u32,
190 b: u32,
191 c: u32,
192 };
193
194 fn doTheTest() !void {
195 var a: U = .{ .a = 100 };
196 var b: U = .{ .b = 200 };
197 var c: U = .{ .c = 300 };
198 inc: switch (a) {
199 .a => |*x| {
200 x.* += 1;
201 continue :inc b;
202 },
203 .b => |*x| {
204 x.* += 10;
205 continue :inc c;
206 },
207 .c => |*x| {
208 x.* += 50;
209 },
210 }
211 try expect(a.a == 101);
212 try expect(b.b == 210);
213 try expect(c.c == 350);
214 }
215 };
216 try S.doTheTest();
217 try comptime S.doTheTest();
218}
219
220test "unanalyzed continue with operand" {
221 @setRuntimeSafety(false);
222 label: switch (false) {
223 false => if (false) continue :label true,
224 true => {},
225 }
226}
227
228test "switch loop on larger than pointer integer" {
229 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
230 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
231 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
232
233 var entry: @Int(.unsigned, @bitSizeOf(usize) + 1) = undefined;
234 entry = 0;
235 loop: switch (entry) {
236 0 => {
237 entry += 1;
238 continue :loop 1;
239 },
240 1 => |x| {
241 entry += 1;
242 continue :loop x + 1;
243 },
244 2 => entry += 1,
245 else => unreachable,
246 }
247 try expect(entry == 3);
248}
249
250test "switch loop on non-exhaustive enum" {
251 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
252 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
253 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
254 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
255
256 const S = struct {
257 const E = enum(u8) { a, b, c, _ };
258
259 fn doTheTest() !void {
260 var start: E = undefined;
261 start = .a;
262 const result: u32 = s: switch (start) {
263 .a => continue :s .c,
264 else => continue :s @enumFromInt(123),
265 .b, _ => |x| break :s @intFromEnum(x),
266 };
267 try expect(result == 123);
268 }
269 };
270 try S.doTheTest();
271 try comptime S.doTheTest();
272}