authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2024-03-28 13:03:38+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2024-03-28 15:24:01+02:00
log2cdc48a6326f61c17947867ed9bf61cba606ce97
treed3c35a73e562f1bcad6f61d30e3ed2888c42e1c0
parent7aa42f47b79f289829a1b43a68c8c08e374aa6a2

remove `test/cbe.zig`

The C backend is far enough along for these tests to be redundant with all the other tests.

2 files changed, 0 insertions(+), 954 deletions(-)

test/cases.zig-1
......@@ -11,7 +11,6 @@ pub const BuildOptions = struct {
1111
1212pub fn addCases(cases: *Cases, build_options: BuildOptions, b: *std.Build) !void {
1313 try @import("compile_errors.zig").addCases(cases, b);
14 try @import("cbe.zig").addCases(cases, b);
1514 try @import("llvm_targets.zig").addCases(cases, build_options, b);
1615 try @import("nvptx.zig").addCases(cases, b);
1716}
test/cbe.zig deleted-953
......@@ -1,953 +0,0 @@
1const std = @import("std");
2const Cases = @import("src/Cases.zig");
3const nl = if (@import("builtin").os.tag == .windows) "\r\n" else "\n";
4
5pub fn addCases(ctx: *Cases, b: *std.Build) !void {
6 // These tests should work with all platforms, but we're using linux_x64 for
7 // now for consistency. Will be expanded eventually.
8 const linux_x64: std.Target.Query = .{
9 .cpu_arch = .x86_64,
10 .os_tag = .linux,
11 };
12
13 {
14 var case = ctx.exeFromCompiledC("hello world with updates", .{}, b);
15
16 // Regular old hello world
17 case.addCompareOutput(
18 \\extern fn puts(s: [*:0]const u8) c_int;
19 \\pub export fn main() c_int {
20 \\ _ = puts("hello world!");
21 \\ return 0;
22 \\}
23 , "hello world!" ++ nl);
24
25 // Now change the message only
26 case.addCompareOutput(
27 \\extern fn puts(s: [*:0]const u8) c_int;
28 \\pub export fn main() c_int {
29 \\ _ = puts("yo");
30 \\ return 0;
31 \\}
32 , "yo" ++ nl);
33
34 // Add an unused Decl
35 case.addCompareOutput(
36 \\extern fn puts(s: [*:0]const u8) c_int;
37 \\pub export fn main() c_int {
38 \\ _ = puts("yo!");
39 \\ return 0;
40 \\}
41 \\fn unused() void {}
42 , "yo!" ++ nl);
43
44 // Comptime return type and calling convention expected.
45 case.addError(
46 \\var x: i32 = 1234;
47 \\pub export fn main() x {
48 \\ return 0;
49 \\}
50 \\export fn foo() callconv(y) c_int {
51 \\ return 0;
52 \\}
53 \\var y: @import("std").builtin.CallingConvention = .C;
54 , &.{
55 ":2:22: error: expected type 'type', found 'i32'",
56 ":5:26: error: unable to resolve comptime value",
57 ":5:26: note: calling convention must be comptime-known",
58 });
59 }
60
61 {
62 var case = ctx.exeFromCompiledC("var args", .{}, b);
63
64 case.addCompareOutput(
65 \\extern fn printf(format: [*:0]const u8, ...) c_int;
66 \\
67 \\pub export fn main() c_int {
68 \\ _ = printf("Hello, %s!\n", "world");
69 \\ return 0;
70 \\}
71 , "Hello, world!" ++ nl);
72 }
73
74 {
75 var case = ctx.exeFromCompiledC("errorFromInt", .{}, b);
76
77 case.addCompareOutput(
78 \\pub export fn main() c_int {
79 \\ // comptime checks
80 \\ const a = error.A;
81 \\ const b = error.B;
82 \\ const c = @errorFromInt(2);
83 \\ const d = @errorFromInt(1);
84 \\ if (!(c == b)) unreachable;
85 \\ if (!(a == d)) unreachable;
86 \\ // runtime checks
87 \\ var x = error.A;
88 \\ var y = error.B;
89 \\ var z = @errorFromInt(2);
90 \\ var f = @errorFromInt(1);
91 \\ if (!(y == z)) unreachable;
92 \\ if (!(x == f)) unreachable;
93 \\ return 0;
94 \\}
95 , "");
96 case.addError(
97 \\pub export fn main() c_int {
98 \\ _ = @errorFromInt(0);
99 \\ return 0;
100 \\}
101 , &.{":2:21: error: integer value '0' represents no error"});
102 case.addError(
103 \\pub export fn main() c_int {
104 \\ _ = @errorFromInt(3);
105 \\ return 0;
106 \\}
107 , &.{":2:21: error: integer value '3' represents no error"});
108 }
109
110 {
111 var case = ctx.exeFromCompiledC("x86_64-linux inline assembly", linux_x64, b);
112
113 // Exit with 0
114 case.addCompareOutput(
115 \\fn exitGood() noreturn {
116 \\ asm volatile ("syscall"
117 \\ :
118 \\ : [number] "{rax}" (231),
119 \\ [arg1] "{rdi}" (0)
120 \\ );
121 \\ unreachable;
122 \\}
123 \\
124 \\pub export fn main() c_int {
125 \\ exitGood();
126 \\}
127 , "");
128
129 // Pass a usize parameter to exit
130 case.addCompareOutput(
131 \\pub export fn main() c_int {
132 \\ exit(0);
133 \\}
134 \\
135 \\fn exit(code: usize) noreturn {
136 \\ asm volatile ("syscall"
137 \\ :
138 \\ : [number] "{rax}" (231),
139 \\ [arg1] "{rdi}" (code)
140 \\ );
141 \\ unreachable;
142 \\}
143 , "");
144
145 // Change the parameter to u8
146 case.addCompareOutput(
147 \\pub export fn main() c_int {
148 \\ exit(0);
149 \\}
150 \\
151 \\fn exit(code: u8) noreturn {
152 \\ asm volatile ("syscall"
153 \\ :
154 \\ : [number] "{rax}" (231),
155 \\ [arg1] "{rdi}" (code)
156 \\ );
157 \\ unreachable;
158 \\}
159 , "");
160
161 // Do some arithmetic at the exit callsite
162 case.addCompareOutput(
163 \\pub export fn main() c_int {
164 \\ exitMath(1);
165 \\}
166 \\
167 \\fn exitMath(a: u8) noreturn {
168 \\ exit(0 + a - a);
169 \\}
170 \\
171 \\fn exit(code: u8) noreturn {
172 \\ asm volatile ("syscall"
173 \\ :
174 \\ : [number] "{rax}" (231),
175 \\ [arg1] "{rdi}" (code)
176 \\ );
177 \\ unreachable;
178 \\}
179 \\
180 , "");
181
182 // Invert the arithmetic
183 case.addCompareOutput(
184 \\pub export fn main() c_int {
185 \\ exitMath(1);
186 \\}
187 \\
188 \\fn exitMath(a: u8) noreturn {
189 \\ exit(a + 0 - a);
190 \\}
191 \\
192 \\fn exit(code: u8) noreturn {
193 \\ asm volatile ("syscall"
194 \\ :
195 \\ : [number] "{rax}" (231),
196 \\ [arg1] "{rdi}" (code)
197 \\ );
198 \\ unreachable;
199 \\}
200 \\
201 , "");
202 }
203
204 {
205 var case = ctx.exeFromCompiledC("alloc and retptr", .{}, b);
206
207 case.addCompareOutput(
208 \\fn add(a: i32, b: i32) i32 {
209 \\ return a + b;
210 \\}
211 \\
212 \\fn addIndirect(a: i32, b: i32) i32 {
213 \\ return add(a, b);
214 \\}
215 \\
216 \\pub export fn main() c_int {
217 \\ return addIndirect(1, 2) - 3;
218 \\}
219 , "");
220 }
221
222 {
223 var case = ctx.exeFromCompiledC("inferred local const and var", .{}, b);
224
225 case.addCompareOutput(
226 \\fn add(a: i32, b: i32) i32 {
227 \\ return a + b;
228 \\}
229 \\
230 \\pub export fn main() c_int {
231 \\ const x = add(1, 2);
232 \\ var y = add(3, 0);
233 \\ y -= x;
234 \\ return y;
235 \\}
236 , "");
237 }
238 {
239 var case = ctx.exeFromCompiledC("control flow", .{}, b);
240
241 // Simple while loop
242 case.addCompareOutput(
243 \\pub export fn main() c_int {
244 \\ var a: c_int = 0;
245 \\ while (a < 5) : (a+=1) {}
246 \\ return a - 5;
247 \\}
248 , "");
249 case.addCompareOutput(
250 \\pub export fn main() c_int {
251 \\ var a = true;
252 \\ while (!a) {}
253 \\ return 0;
254 \\}
255 , "");
256
257 // If expression
258 case.addCompareOutput(
259 \\pub export fn main() c_int {
260 \\ var cond: c_int = 0;
261 \\ var a: c_int = @as(c_int, if (cond == 0)
262 \\ 2
263 \\ else
264 \\ 3) + 9;
265 \\ return a - 11;
266 \\}
267 , "");
268
269 // If expression with breakpoint that does not get hit
270 case.addCompareOutput(
271 \\pub export fn main() c_int {
272 \\ var x: i32 = 1;
273 \\ if (x != 1) @breakpoint();
274 \\ return 0;
275 \\}
276 , "");
277
278 // Switch expression
279 case.addCompareOutput(
280 \\pub export fn main() c_int {
281 \\ var cond: c_int = 0;
282 \\ var a: c_int = switch (cond) {
283 \\ 1 => 1,
284 \\ 2 => 2,
285 \\ 99...300, 12 => 3,
286 \\ 0 => 4,
287 \\ else => 5,
288 \\ };
289 \\ return a - 4;
290 \\}
291 , "");
292
293 // Switch expression missing else case.
294 case.addError(
295 \\pub export fn main() c_int {
296 \\ var cond: c_int = 0;
297 \\ const a: c_int = switch (cond) {
298 \\ 1 => 1,
299 \\ 2 => 2,
300 \\ 3 => 3,
301 \\ 4 => 4,
302 \\ };
303 \\ return a - 4;
304 \\}
305 , &.{":3:22: error: switch must handle all possibilities"});
306
307 // Switch expression, has an unreachable prong.
308 case.addCompareOutput(
309 \\pub export fn main() c_int {
310 \\ var cond: c_int = 0;
311 \\ const a: c_int = switch (cond) {
312 \\ 1 => 1,
313 \\ 2 => 2,
314 \\ 99...300, 12 => 3,
315 \\ 0 => 4,
316 \\ 13 => unreachable,
317 \\ else => 5,
318 \\ };
319 \\ return a - 4;
320 \\}
321 , "");
322
323 // Switch expression, has an unreachable prong and prongs write
324 // to result locations.
325 case.addCompareOutput(
326 \\pub export fn main() c_int {
327 \\ var cond: c_int = 0;
328 \\ var a: c_int = switch (cond) {
329 \\ 1 => 1,
330 \\ 2 => 2,
331 \\ 99...300, 12 => 3,
332 \\ 0 => 4,
333 \\ 13 => unreachable,
334 \\ else => 5,
335 \\ };
336 \\ return a - 4;
337 \\}
338 , "");
339
340 // Integer switch expression has duplicate case value.
341 case.addError(
342 \\pub export fn main() c_int {
343 \\ var cond: c_int = 0;
344 \\ const a: c_int = switch (cond) {
345 \\ 1 => 1,
346 \\ 2 => 2,
347 \\ 96, 11...13, 97 => 3,
348 \\ 0 => 4,
349 \\ 90, 12 => 100,
350 \\ else => 5,
351 \\ };
352 \\ return a - 4;
353 \\}
354 , &.{
355 ":8:13: error: duplicate switch value",
356 ":6:15: note: previous value here",
357 });
358
359 // Boolean switch expression has duplicate case value.
360 case.addError(
361 \\pub export fn main() c_int {
362 \\ var a: bool = false;
363 \\ const b: c_int = switch (a) {
364 \\ false => 1,
365 \\ true => 2,
366 \\ false => 3,
367 \\ };
368 \\ _ = b;
369 \\}
370 , &.{
371 ":6:9: error: duplicate switch value",
372 });
373
374 // Sparse (no range capable) switch expression has duplicate case value.
375 case.addError(
376 \\pub export fn main() c_int {
377 \\ const A: type = i32;
378 \\ const b: c_int = switch (A) {
379 \\ i32 => 1,
380 \\ bool => 2,
381 \\ f64, i32 => 3,
382 \\ else => 4,
383 \\ };
384 \\ _ = b;
385 \\}
386 , &.{
387 ":6:14: error: duplicate switch value",
388 ":4:9: note: previous value here",
389 });
390
391 // Ranges not allowed for some kinds of switches.
392 case.addError(
393 \\pub export fn main() c_int {
394 \\ const A: type = i32;
395 \\ const b: c_int = switch (A) {
396 \\ i32 => 1,
397 \\ bool => 2,
398 \\ f16...f64 => 3,
399 \\ else => 4,
400 \\ };
401 \\ _ = b;
402 \\}
403 , &.{
404 ":3:30: error: ranges not allowed when switching on type 'type'",
405 ":6:12: note: range here",
406 });
407
408 // Switch expression has unreachable else prong.
409 case.addError(
410 \\pub export fn main() c_int {
411 \\ var a: u2 = 0;
412 \\ const b: i32 = switch (a) {
413 \\ 0 => 10,
414 \\ 1 => 20,
415 \\ 2 => 30,
416 \\ 3 => 40,
417 \\ else => 50,
418 \\ };
419 \\ _ = b;
420 \\}
421 , &.{
422 ":8:14: error: unreachable else prong; all cases already handled",
423 });
424 }
425 //{
426 // var case = ctx.exeFromCompiledC("optionals", .{}, b);
427
428 // // Simple while loop
429 // case.addCompareOutput(
430 // \\pub export fn main() c_int {
431 // \\ var count: c_int = 0;
432 // \\ var opt_ptr: ?*c_int = &count;
433 // \\ while (opt_ptr) |_| : (count += 1) {
434 // \\ if (count == 4) opt_ptr = null;
435 // \\ }
436 // \\ return count - 5;
437 // \\}
438 // , "");
439
440 // // Same with non pointer optionals
441 // case.addCompareOutput(
442 // \\pub export fn main() c_int {
443 // \\ var count: c_int = 0;
444 // \\ var opt_ptr: ?c_int = count;
445 // \\ while (opt_ptr) |_| : (count += 1) {
446 // \\ if (count == 4) opt_ptr = null;
447 // \\ }
448 // \\ return count - 5;
449 // \\}
450 // , "");
451 //}
452
453 {
454 var case = ctx.exeFromCompiledC("errors", .{}, b);
455 case.addCompareOutput(
456 \\pub export fn main() c_int {
457 \\ var e1 = error.Foo;
458 \\ var e2 = error.Bar;
459 \\ assert(e1 != e2);
460 \\ assert(e1 == error.Foo);
461 \\ assert(e2 == error.Bar);
462 \\ return 0;
463 \\}
464 \\fn assert(b: bool) void {
465 \\ if (!b) unreachable;
466 \\}
467 , "");
468 case.addCompareOutput(
469 \\pub export fn main() c_int {
470 \\ var e: anyerror!c_int = 0;
471 \\ const i = e catch 69;
472 \\ return i;
473 \\}
474 , "");
475 case.addCompareOutput(
476 \\pub export fn main() c_int {
477 \\ var e: anyerror!c_int = error.Foo;
478 \\ const i = e catch 69;
479 \\ return 69 - i;
480 \\}
481 , "");
482 case.addCompareOutput(
483 \\const E = error{e};
484 \\const S = struct { x: u32 };
485 \\fn f() E!u32 {
486 \\ const x = (try @as(E!S, S{ .x = 1 })).x;
487 \\ return x;
488 \\}
489 \\pub export fn main() c_int {
490 \\ const x = f() catch @as(u32, 0);
491 \\ if (x != 1) unreachable;
492 \\ return 0;
493 \\}
494 , "");
495 }
496
497 {
498 var case = ctx.exeFromCompiledC("structs", .{}, b);
499 case.addError(
500 \\const Point = struct { x: i32, y: i32 };
501 \\pub export fn main() c_int {
502 \\ var p: Point = .{
503 \\ .y = 24,
504 \\ .x = 12,
505 \\ .y = 24,
506 \\ };
507 \\ return p.y - p.x - p.x;
508 \\}
509 , &.{
510 ":4:10: error: duplicate struct field name",
511 ":6:10: note: duplicate name here",
512 ":3:21: note: struct declared here",
513 });
514 case.addError(
515 \\const Point = struct { x: i32, y: i32 };
516 \\pub export fn main() c_int {
517 \\ var p: Point = .{
518 \\ .y = 24,
519 \\ };
520 \\ return p.y - p.x - p.x;
521 \\}
522 , &.{
523 ":3:21: error: missing struct field: x",
524 ":1:15: note: struct 'tmp.Point' declared here",
525 });
526 case.addError(
527 \\const Point = struct { x: i32, y: i32 };
528 \\pub export fn main() c_int {
529 \\ var p: Point = .{
530 \\ .x = 12,
531 \\ .y = 24,
532 \\ .z = 48,
533 \\ };
534 \\ return p.y - p.x - p.x;
535 \\}
536 , &.{
537 ":6:10: error: no field named 'z' in struct 'tmp.Point'",
538 ":1:15: note: struct declared here",
539 });
540 case.addCompareOutput(
541 \\const Point = struct { x: i32, y: i32 };
542 \\pub export fn main() c_int {
543 \\ var p: Point = .{
544 \\ .x = 12,
545 \\ .y = 24,
546 \\ };
547 \\ return p.y - p.x - p.x;
548 \\}
549 , "");
550 case.addCompareOutput(
551 \\const Point = struct { x: i32, y: i32, z: i32, a: i32, b: i32 };
552 \\pub export fn main() c_int {
553 \\ var p: Point = .{
554 \\ .x = 18,
555 \\ .y = 24,
556 \\ .z = 1,
557 \\ .a = 2,
558 \\ .b = 3,
559 \\ };
560 \\ return p.y - p.x - p.z - p.a - p.b;
561 \\}
562 , "");
563 }
564
565 {
566 var case = ctx.exeFromCompiledC("unions", .{}, b);
567
568 case.addError(
569 \\const U = union {
570 \\ a: u32,
571 \\ b
572 \\};
573 , &.{
574 ":3:5: error: union field missing type",
575 });
576
577 case.addError(
578 \\const E = enum { a, b };
579 \\const U = union(E) {
580 \\ a: u32 = 1,
581 \\ b: f32 = 2,
582 \\};
583 , &.{
584 ":2:11: error: explicitly valued tagged union requires inferred enum tag type",
585 ":3:14: note: tag value specified here",
586 });
587
588 case.addError(
589 \\const U = union(enum) {
590 \\ a: u32 = 1,
591 \\ b: f32 = 2,
592 \\};
593 , &.{
594 ":1:11: error: explicitly valued tagged union missing integer tag type",
595 ":2:14: note: tag value specified here",
596 });
597 }
598
599 {
600 var case = ctx.exeFromCompiledC("enums", .{}, b);
601
602 case.addError(
603 \\const E1 = packed enum { a, b, c };
604 \\const E2 = extern enum { a, b, c };
605 \\export fn foo() void {
606 \\ _ = E1.a;
607 \\}
608 \\export fn bar() void {
609 \\ _ = E2.a;
610 \\}
611 , &.{
612 ":1:12: error: enums do not support 'packed' or 'extern'; instead provide an explicit integer tag type",
613 ":2:12: error: enums do not support 'packed' or 'extern'; instead provide an explicit integer tag type",
614 });
615
616 // comptime and types are caught in AstGen.
617 case.addError(
618 \\const E1 = enum {
619 \\ a,
620 \\ comptime b,
621 \\ c,
622 \\};
623 \\const E2 = enum {
624 \\ a,
625 \\ b: i32,
626 \\ c,
627 \\};
628 \\export fn foo() void {
629 \\ _ = E1.a;
630 \\}
631 \\export fn bar() void {
632 \\ _ = E2.a;
633 \\}
634 , &.{
635 ":3:5: error: enum fields cannot be marked comptime",
636 ":8:8: error: enum fields do not have types",
637 ":6:12: note: consider 'union(enum)' here to make it a tagged union",
638 });
639
640 // @intFromEnum, @enumFromInt, enum literal coercion, field access syntax, comparison, switch
641 case.addCompareOutput(
642 \\const Number = enum { One, Two, Three };
643 \\
644 \\pub export fn main() c_int {
645 \\ var number1 = Number.One;
646 \\ var number2: Number = .Two;
647 \\ const number3: Number = @enumFromInt(2);
648 \\ if (number1 == number2) return 1;
649 \\ if (number2 == number3) return 1;
650 \\ if (@intFromEnum(number1) != 0) return 1;
651 \\ if (@intFromEnum(number2) != 1) return 1;
652 \\ if (@intFromEnum(number3) != 2) return 1;
653 \\ var x: Number = .Two;
654 \\ if (number2 != x) return 1;
655 \\ switch (x) {
656 \\ .One => return 1,
657 \\ .Two => return 0,
658 \\ number3 => return 2,
659 \\ }
660 \\}
661 , "");
662
663 // Specifying alignment is a parse error.
664 // This also tests going from a successful build to a parse error.
665 case.addError(
666 \\const E1 = enum {
667 \\ a,
668 \\ b align(4),
669 \\ c,
670 \\};
671 \\export fn foo() void {
672 \\ _ = E1.a;
673 \\}
674 , &.{
675 ":3:13: error: enum fields cannot be aligned",
676 });
677
678 // Redundant non-exhaustive enum mark.
679 // This also tests going from a parse error to an AstGen error.
680 case.addError(
681 \\const E1 = enum {
682 \\ a,
683 \\ _,
684 \\ b,
685 \\ c,
686 \\ _,
687 \\};
688 \\export fn foo() void {
689 \\ _ = E1.a;
690 \\}
691 , &.{
692 ":6:5: error: redundant non-exhaustive enum mark",
693 ":3:5: note: other mark here",
694 });
695
696 case.addError(
697 \\const E1 = enum {
698 \\ a,
699 \\ b,
700 \\ c,
701 \\ _ = 10,
702 \\};
703 \\export fn foo() void {
704 \\ _ = E1.a;
705 \\}
706 , &.{
707 ":5:9: error: '_' is used to mark an enum as non-exhaustive and cannot be assigned a value",
708 });
709
710 case.addError(
711 \\const E1 = enum { a, b, _ };
712 \\export fn foo() void {
713 \\ _ = E1.a;
714 \\}
715 , &.{
716 ":1:12: error: non-exhaustive enum missing integer tag type",
717 ":1:25: note: marked non-exhaustive here",
718 });
719
720 case.addError(
721 \\const E1 = enum { a, b, c, b, d };
722 \\pub export fn main() c_int {
723 \\ _ = E1.a;
724 \\}
725 , &.{
726 ":1:22: error: duplicate enum field name",
727 ":1:28: note: duplicate field here",
728 ":1:12: note: enum declared here",
729 });
730
731 case.addError(
732 \\pub export fn main() c_int {
733 \\ const a = true;
734 \\ _ = @intFromEnum(a);
735 \\}
736 , &.{
737 ":3:20: error: expected enum or tagged union, found 'bool'",
738 });
739
740 case.addError(
741 \\pub export fn main() c_int {
742 \\ const a = 1;
743 \\ _ = @as(bool, @enumFromInt(a));
744 \\}
745 , &.{
746 ":3:19: error: expected enum, found 'bool'",
747 });
748
749 case.addError(
750 \\const E = enum { a, b, c };
751 \\pub export fn main() c_int {
752 \\ _ = @as(E, @enumFromInt(3));
753 \\}
754 , &.{
755 ":3:16: error: enum 'tmp.E' has no tag with value '3'",
756 ":1:11: note: enum declared here",
757 });
758
759 case.addError(
760 \\const E = enum { a, b, c };
761 \\pub export fn main() c_int {
762 \\ var x: E = .a;
763 \\ switch (x) {
764 \\ .a => {},
765 \\ .c => {},
766 \\ }
767 \\}
768 , &.{
769 ":4:5: error: switch must handle all possibilities",
770 ":1:21: note: unhandled enumeration value: 'b'",
771 ":1:11: note: enum 'tmp.E' declared here",
772 });
773
774 case.addError(
775 \\const E = enum { a, b, c };
776 \\pub export fn main() c_int {
777 \\ var x: E = .a;
778 \\ switch (x) {
779 \\ .a => {},
780 \\ .b => {},
781 \\ .b => {},
782 \\ .c => {},
783 \\ }
784 \\}
785 , &.{
786 ":7:10: error: duplicate switch value",
787 ":6:10: note: previous value here",
788 });
789
790 case.addError(
791 \\const E = enum { a, b, c };
792 \\pub export fn main() c_int {
793 \\ var x: E = .a;
794 \\ switch (x) {
795 \\ .a => {},
796 \\ .b => {},
797 \\ .c => {},
798 \\ else => {},
799 \\ }
800 \\}
801 , &.{
802 ":8:14: error: unreachable else prong; all cases already handled",
803 });
804
805 case.addError(
806 \\const E = enum { a, b, c };
807 \\pub export fn main() c_int {
808 \\ var x: E = .a;
809 \\ switch (x) {
810 \\ .a => {},
811 \\ .b => {},
812 \\ _ => {},
813 \\ }
814 \\}
815 , &.{
816 ":4:5: error: '_' prong only allowed when switching on non-exhaustive enums",
817 ":7:11: note: '_' prong here",
818 });
819
820 case.addError(
821 \\const E = enum { a, b, c };
822 \\pub export fn main() c_int {
823 \\ _ = E.d;
824 \\}
825 , &.{
826 ":3:11: error: enum 'tmp.E' has no member named 'd'",
827 ":1:11: note: enum declared here",
828 });
829
830 case.addError(
831 \\const E = enum { a, b, c };
832 \\pub export fn main() c_int {
833 \\ var x: E = .d;
834 \\ _ = x;
835 \\}
836 , &.{
837 ":3:17: error: no field named 'd' in enum 'tmp.E'",
838 ":1:11: note: enum declared here",
839 });
840 }
841
842 {
843 var case = ctx.exeFromCompiledC("shift right and left", .{}, b);
844 case.addCompareOutput(
845 \\pub export fn main() c_int {
846 \\ var i: u32 = 16;
847 \\ assert(i >> 1, 8);
848 \\ return 0;
849 \\}
850 \\fn assert(a: u32, b: u32) void {
851 \\ if (a != b) unreachable;
852 \\}
853 , "");
854
855 case.addCompareOutput(
856 \\pub export fn main() c_int {
857 \\ var i: u32 = 16;
858 \\ assert(i << 1, 32);
859 \\ return 0;
860 \\}
861 \\fn assert(a: u32, b: u32) void {
862 \\ if (a != b) unreachable;
863 \\}
864 , "");
865 }
866
867 {
868 var case = ctx.exeFromCompiledC("inferred error sets", .{}, b);
869
870 case.addCompareOutput(
871 \\pub export fn main() c_int {
872 \\ if (foo()) |_| {
873 \\ @panic("test fail");
874 \\ } else |err| {
875 \\ if (err != error.ItBroke) {
876 \\ @panic("test fail");
877 \\ }
878 \\ }
879 \\ return 0;
880 \\}
881 \\fn foo() !void {
882 \\ return error.ItBroke;
883 \\}
884 , "");
885 }
886
887 {
888 // TODO: add u64 tests, ran into issues with the literal generated for std.math.maxInt(u64)
889 var case = ctx.exeFromCompiledC("add and sub wrapping operations", .{}, b);
890 case.addCompareOutput(
891 \\pub export fn main() c_int {
892 \\ // Addition
893 \\ if (!add_u3(1, 1, 2)) return 1;
894 \\ if (!add_u3(7, 1, 0)) return 1;
895 \\ if (!add_i3(1, 1, 2)) return 1;
896 \\ if (!add_i3(3, 2, -3)) return 1;
897 \\ if (!add_i3(-3, -2, 3)) return 1;
898 \\ if (!add_c_int(1, 1, 2)) return 1;
899 \\ // TODO enable these when stage2 supports std.math.maxInt
900 \\ //if (!add_c_int(maxInt(c_int), 2, minInt(c_int) + 1)) return 1;
901 \\ //if (!add_c_int(maxInt(c_int) + 1, -2, maxInt(c_int))) return 1;
902 \\
903 \\ // Subtraction
904 \\ if (!sub_u3(2, 1, 1)) return 1;
905 \\ if (!sub_u3(0, 1, 7)) return 1;
906 \\ if (!sub_i3(2, 1, 1)) return 1;
907 \\ if (!sub_i3(3, -2, -3)) return 1;
908 \\ if (!sub_i3(-3, 2, 3)) return 1;
909 \\ if (!sub_c_int(2, 1, 1)) return 1;
910 \\ // TODO enable these when stage2 supports std.math.maxInt
911 \\ //if (!sub_c_int(maxInt(c_int), -2, minInt(c_int) + 1)) return 1;
912 \\ //if (!sub_c_int(minInt(c_int) + 1, 2, maxInt(c_int))) return 1;
913 \\
914 \\ return 0;
915 \\}
916 \\fn add_u3(lhs: u3, rhs: u3, expected: u3) bool {
917 \\ return expected == lhs +% rhs;
918 \\}
919 \\fn add_i3(lhs: i3, rhs: i3, expected: i3) bool {
920 \\ return expected == lhs +% rhs;
921 \\}
922 \\fn add_c_int(lhs: c_int, rhs: c_int, expected: c_int) bool {
923 \\ return expected == lhs +% rhs;
924 \\}
925 \\fn sub_u3(lhs: u3, rhs: u3, expected: u3) bool {
926 \\ return expected == lhs -% rhs;
927 \\}
928 \\fn sub_i3(lhs: i3, rhs: i3, expected: i3) bool {
929 \\ return expected == lhs -% rhs;
930 \\}
931 \\fn sub_c_int(lhs: c_int, rhs: c_int, expected: c_int) bool {
932 \\ return expected == lhs -% rhs;
933 \\}
934 , "");
935 }
936
937 {
938 var case = ctx.exeFromCompiledC("rem", linux_x64, b);
939 case.addCompareOutput(
940 \\fn assert(ok: bool) void {
941 \\ if (!ok) unreachable;
942 \\}
943 \\fn rem(lhs: i32, rhs: i32, expected: i32) bool {
944 \\ return @rem(lhs, rhs) == expected;
945 \\}
946 \\pub export fn main() c_int {
947 \\ assert(rem(-5, 3, -2));
948 \\ assert(rem(5, 3, 2));
949 \\ return 0;
950 \\}
951 , "");
952 }
953}