Commit 2cdc48a632
test/cases.zig
@@ -11,7 +11,6 @@ pub const BuildOptions = struct {
pub fn addCases(cases: *Cases, build_options: BuildOptions, b: *std.Build) !void {
try @import("compile_errors.zig").addCases(cases, b);
- try @import("cbe.zig").addCases(cases, b);
try @import("llvm_targets.zig").addCases(cases, build_options, b);
try @import("nvptx.zig").addCases(cases, b);
}
test/cbe.zig
@@ -1,953 +0,0 @@
-const std = @import("std");
-const Cases = @import("src/Cases.zig");
-const nl = if (@import("builtin").os.tag == .windows) "\r\n" else "\n";
-
-pub fn addCases(ctx: *Cases, b: *std.Build) !void {
- // These tests should work with all platforms, but we're using linux_x64 for
- // now for consistency. Will be expanded eventually.
- const linux_x64: std.Target.Query = .{
- .cpu_arch = .x86_64,
- .os_tag = .linux,
- };
-
- {
- var case = ctx.exeFromCompiledC("hello world with updates", .{}, b);
-
- // Regular old hello world
- case.addCompareOutput(
- \\extern fn puts(s: [*:0]const u8) c_int;
- \\pub export fn main() c_int {
- \\ _ = puts("hello world!");
- \\ return 0;
- \\}
- , "hello world!" ++ nl);
-
- // Now change the message only
- case.addCompareOutput(
- \\extern fn puts(s: [*:0]const u8) c_int;
- \\pub export fn main() c_int {
- \\ _ = puts("yo");
- \\ return 0;
- \\}
- , "yo" ++ nl);
-
- // Add an unused Decl
- case.addCompareOutput(
- \\extern fn puts(s: [*:0]const u8) c_int;
- \\pub export fn main() c_int {
- \\ _ = puts("yo!");
- \\ return 0;
- \\}
- \\fn unused() void {}
- , "yo!" ++ nl);
-
- // Comptime return type and calling convention expected.
- case.addError(
- \\var x: i32 = 1234;
- \\pub export fn main() x {
- \\ return 0;
- \\}
- \\export fn foo() callconv(y) c_int {
- \\ return 0;
- \\}
- \\var y: @import("std").builtin.CallingConvention = .C;
- , &.{
- ":2:22: error: expected type 'type', found 'i32'",
- ":5:26: error: unable to resolve comptime value",
- ":5:26: note: calling convention must be comptime-known",
- });
- }
-
- {
- var case = ctx.exeFromCompiledC("var args", .{}, b);
-
- case.addCompareOutput(
- \\extern fn printf(format: [*:0]const u8, ...) c_int;
- \\
- \\pub export fn main() c_int {
- \\ _ = printf("Hello, %s!\n", "world");
- \\ return 0;
- \\}
- , "Hello, world!" ++ nl);
- }
-
- {
- var case = ctx.exeFromCompiledC("errorFromInt", .{}, b);
-
- case.addCompareOutput(
- \\pub export fn main() c_int {
- \\ // comptime checks
- \\ const a = error.A;
- \\ const b = error.B;
- \\ const c = @errorFromInt(2);
- \\ const d = @errorFromInt(1);
- \\ if (!(c == b)) unreachable;
- \\ if (!(a == d)) unreachable;
- \\ // runtime checks
- \\ var x = error.A;
- \\ var y = error.B;
- \\ var z = @errorFromInt(2);
- \\ var f = @errorFromInt(1);
- \\ if (!(y == z)) unreachable;
- \\ if (!(x == f)) unreachable;
- \\ return 0;
- \\}
- , "");
- case.addError(
- \\pub export fn main() c_int {
- \\ _ = @errorFromInt(0);
- \\ return 0;
- \\}
- , &.{":2:21: error: integer value '0' represents no error"});
- case.addError(
- \\pub export fn main() c_int {
- \\ _ = @errorFromInt(3);
- \\ return 0;
- \\}
- , &.{":2:21: error: integer value '3' represents no error"});
- }
-
- {
- var case = ctx.exeFromCompiledC("x86_64-linux inline assembly", linux_x64, b);
-
- // Exit with 0
- case.addCompareOutput(
- \\fn exitGood() noreturn {
- \\ asm volatile ("syscall"
- \\ :
- \\ : [number] "{rax}" (231),
- \\ [arg1] "{rdi}" (0)
- \\ );
- \\ unreachable;
- \\}
- \\
- \\pub export fn main() c_int {
- \\ exitGood();
- \\}
- , "");
-
- // Pass a usize parameter to exit
- case.addCompareOutput(
- \\pub export fn main() c_int {
- \\ exit(0);
- \\}
- \\
- \\fn exit(code: usize) noreturn {
- \\ asm volatile ("syscall"
- \\ :
- \\ : [number] "{rax}" (231),
- \\ [arg1] "{rdi}" (code)
- \\ );
- \\ unreachable;
- \\}
- , "");
-
- // Change the parameter to u8
- case.addCompareOutput(
- \\pub export fn main() c_int {
- \\ exit(0);
- \\}
- \\
- \\fn exit(code: u8) noreturn {
- \\ asm volatile ("syscall"
- \\ :
- \\ : [number] "{rax}" (231),
- \\ [arg1] "{rdi}" (code)
- \\ );
- \\ unreachable;
- \\}
- , "");
-
- // Do some arithmetic at the exit callsite
- case.addCompareOutput(
- \\pub export fn main() c_int {
- \\ exitMath(1);
- \\}
- \\
- \\fn exitMath(a: u8) noreturn {
- \\ exit(0 + a - a);
- \\}
- \\
- \\fn exit(code: u8) noreturn {
- \\ asm volatile ("syscall"
- \\ :
- \\ : [number] "{rax}" (231),
- \\ [arg1] "{rdi}" (code)
- \\ );
- \\ unreachable;
- \\}
- \\
- , "");
-
- // Invert the arithmetic
- case.addCompareOutput(
- \\pub export fn main() c_int {
- \\ exitMath(1);
- \\}
- \\
- \\fn exitMath(a: u8) noreturn {
- \\ exit(a + 0 - a);
- \\}
- \\
- \\fn exit(code: u8) noreturn {
- \\ asm volatile ("syscall"
- \\ :
- \\ : [number] "{rax}" (231),
- \\ [arg1] "{rdi}" (code)
- \\ );
- \\ unreachable;
- \\}
- \\
- , "");
- }
-
- {
- var case = ctx.exeFromCompiledC("alloc and retptr", .{}, b);
-
- case.addCompareOutput(
- \\fn add(a: i32, b: i32) i32 {
- \\ return a + b;
- \\}
- \\
- \\fn addIndirect(a: i32, b: i32) i32 {
- \\ return add(a, b);
- \\}
- \\
- \\pub export fn main() c_int {
- \\ return addIndirect(1, 2) - 3;
- \\}
- , "");
- }
-
- {
- var case = ctx.exeFromCompiledC("inferred local const and var", .{}, b);
-
- case.addCompareOutput(
- \\fn add(a: i32, b: i32) i32 {
- \\ return a + b;
- \\}
- \\
- \\pub export fn main() c_int {
- \\ const x = add(1, 2);
- \\ var y = add(3, 0);
- \\ y -= x;
- \\ return y;
- \\}
- , "");
- }
- {
- var case = ctx.exeFromCompiledC("control flow", .{}, b);
-
- // Simple while loop
- case.addCompareOutput(
- \\pub export fn main() c_int {
- \\ var a: c_int = 0;
- \\ while (a < 5) : (a+=1) {}
- \\ return a - 5;
- \\}
- , "");
- case.addCompareOutput(
- \\pub export fn main() c_int {
- \\ var a = true;
- \\ while (!a) {}
- \\ return 0;
- \\}
- , "");
-
- // If expression
- case.addCompareOutput(
- \\pub export fn main() c_int {
- \\ var cond: c_int = 0;
- \\ var a: c_int = @as(c_int, if (cond == 0)
- \\ 2
- \\ else
- \\ 3) + 9;
- \\ return a - 11;
- \\}
- , "");
-
- // If expression with breakpoint that does not get hit
- case.addCompareOutput(
- \\pub export fn main() c_int {
- \\ var x: i32 = 1;
- \\ if (x != 1) @breakpoint();
- \\ return 0;
- \\}
- , "");
-
- // Switch expression
- case.addCompareOutput(
- \\pub export fn main() c_int {
- \\ var cond: c_int = 0;
- \\ var a: c_int = switch (cond) {
- \\ 1 => 1,
- \\ 2 => 2,
- \\ 99...300, 12 => 3,
- \\ 0 => 4,
- \\ else => 5,
- \\ };
- \\ return a - 4;
- \\}
- , "");
-
- // Switch expression missing else case.
- case.addError(
- \\pub export fn main() c_int {
- \\ var cond: c_int = 0;
- \\ const a: c_int = switch (cond) {
- \\ 1 => 1,
- \\ 2 => 2,
- \\ 3 => 3,
- \\ 4 => 4,
- \\ };
- \\ return a - 4;
- \\}
- , &.{":3:22: error: switch must handle all possibilities"});
-
- // Switch expression, has an unreachable prong.
- case.addCompareOutput(
- \\pub export fn main() c_int {
- \\ var cond: c_int = 0;
- \\ const a: c_int = switch (cond) {
- \\ 1 => 1,
- \\ 2 => 2,
- \\ 99...300, 12 => 3,
- \\ 0 => 4,
- \\ 13 => unreachable,
- \\ else => 5,
- \\ };
- \\ return a - 4;
- \\}
- , "");
-
- // Switch expression, has an unreachable prong and prongs write
- // to result locations.
- case.addCompareOutput(
- \\pub export fn main() c_int {
- \\ var cond: c_int = 0;
- \\ var a: c_int = switch (cond) {
- \\ 1 => 1,
- \\ 2 => 2,
- \\ 99...300, 12 => 3,
- \\ 0 => 4,
- \\ 13 => unreachable,
- \\ else => 5,
- \\ };
- \\ return a - 4;
- \\}
- , "");
-
- // Integer switch expression has duplicate case value.
- case.addError(
- \\pub export fn main() c_int {
- \\ var cond: c_int = 0;
- \\ const a: c_int = switch (cond) {
- \\ 1 => 1,
- \\ 2 => 2,
- \\ 96, 11...13, 97 => 3,
- \\ 0 => 4,
- \\ 90, 12 => 100,
- \\ else => 5,
- \\ };
- \\ return a - 4;
- \\}
- , &.{
- ":8:13: error: duplicate switch value",
- ":6:15: note: previous value here",
- });
-
- // Boolean switch expression has duplicate case value.
- case.addError(
- \\pub export fn main() c_int {
- \\ var a: bool = false;
- \\ const b: c_int = switch (a) {
- \\ false => 1,
- \\ true => 2,
- \\ false => 3,
- \\ };
- \\ _ = b;
- \\}
- , &.{
- ":6:9: error: duplicate switch value",
- });
-
- // Sparse (no range capable) switch expression has duplicate case value.
- case.addError(
- \\pub export fn main() c_int {
- \\ const A: type = i32;
- \\ const b: c_int = switch (A) {
- \\ i32 => 1,
- \\ bool => 2,
- \\ f64, i32 => 3,
- \\ else => 4,
- \\ };
- \\ _ = b;
- \\}
- , &.{
- ":6:14: error: duplicate switch value",
- ":4:9: note: previous value here",
- });
-
- // Ranges not allowed for some kinds of switches.
- case.addError(
- \\pub export fn main() c_int {
- \\ const A: type = i32;
- \\ const b: c_int = switch (A) {
- \\ i32 => 1,
- \\ bool => 2,
- \\ f16...f64 => 3,
- \\ else => 4,
- \\ };
- \\ _ = b;
- \\}
- , &.{
- ":3:30: error: ranges not allowed when switching on type 'type'",
- ":6:12: note: range here",
- });
-
- // Switch expression has unreachable else prong.
- case.addError(
- \\pub export fn main() c_int {
- \\ var a: u2 = 0;
- \\ const b: i32 = switch (a) {
- \\ 0 => 10,
- \\ 1 => 20,
- \\ 2 => 30,
- \\ 3 => 40,
- \\ else => 50,
- \\ };
- \\ _ = b;
- \\}
- , &.{
- ":8:14: error: unreachable else prong; all cases already handled",
- });
- }
- //{
- // var case = ctx.exeFromCompiledC("optionals", .{}, b);
-
- // // Simple while loop
- // case.addCompareOutput(
- // \\pub export fn main() c_int {
- // \\ var count: c_int = 0;
- // \\ var opt_ptr: ?*c_int = &count;
- // \\ while (opt_ptr) |_| : (count += 1) {
- // \\ if (count == 4) opt_ptr = null;
- // \\ }
- // \\ return count - 5;
- // \\}
- // , "");
-
- // // Same with non pointer optionals
- // case.addCompareOutput(
- // \\pub export fn main() c_int {
- // \\ var count: c_int = 0;
- // \\ var opt_ptr: ?c_int = count;
- // \\ while (opt_ptr) |_| : (count += 1) {
- // \\ if (count == 4) opt_ptr = null;
- // \\ }
- // \\ return count - 5;
- // \\}
- // , "");
- //}
-
- {
- var case = ctx.exeFromCompiledC("errors", .{}, b);
- case.addCompareOutput(
- \\pub export fn main() c_int {
- \\ var e1 = error.Foo;
- \\ var e2 = error.Bar;
- \\ assert(e1 != e2);
- \\ assert(e1 == error.Foo);
- \\ assert(e2 == error.Bar);
- \\ return 0;
- \\}
- \\fn assert(b: bool) void {
- \\ if (!b) unreachable;
- \\}
- , "");
- case.addCompareOutput(
- \\pub export fn main() c_int {
- \\ var e: anyerror!c_int = 0;
- \\ const i = e catch 69;
- \\ return i;
- \\}
- , "");
- case.addCompareOutput(
- \\pub export fn main() c_int {
- \\ var e: anyerror!c_int = error.Foo;
- \\ const i = e catch 69;
- \\ return 69 - i;
- \\}
- , "");
- case.addCompareOutput(
- \\const E = error{e};
- \\const S = struct { x: u32 };
- \\fn f() E!u32 {
- \\ const x = (try @as(E!S, S{ .x = 1 })).x;
- \\ return x;
- \\}
- \\pub export fn main() c_int {
- \\ const x = f() catch @as(u32, 0);
- \\ if (x != 1) unreachable;
- \\ return 0;
- \\}
- , "");
- }
-
- {
- var case = ctx.exeFromCompiledC("structs", .{}, b);
- case.addError(
- \\const Point = struct { x: i32, y: i32 };
- \\pub export fn main() c_int {
- \\ var p: Point = .{
- \\ .y = 24,
- \\ .x = 12,
- \\ .y = 24,
- \\ };
- \\ return p.y - p.x - p.x;
- \\}
- , &.{
- ":4:10: error: duplicate struct field name",
- ":6:10: note: duplicate name here",
- ":3:21: note: struct declared here",
- });
- case.addError(
- \\const Point = struct { x: i32, y: i32 };
- \\pub export fn main() c_int {
- \\ var p: Point = .{
- \\ .y = 24,
- \\ };
- \\ return p.y - p.x - p.x;
- \\}
- , &.{
- ":3:21: error: missing struct field: x",
- ":1:15: note: struct 'tmp.Point' declared here",
- });
- case.addError(
- \\const Point = struct { x: i32, y: i32 };
- \\pub export fn main() c_int {
- \\ var p: Point = .{
- \\ .x = 12,
- \\ .y = 24,
- \\ .z = 48,
- \\ };
- \\ return p.y - p.x - p.x;
- \\}
- , &.{
- ":6:10: error: no field named 'z' in struct 'tmp.Point'",
- ":1:15: note: struct declared here",
- });
- case.addCompareOutput(
- \\const Point = struct { x: i32, y: i32 };
- \\pub export fn main() c_int {
- \\ var p: Point = .{
- \\ .x = 12,
- \\ .y = 24,
- \\ };
- \\ return p.y - p.x - p.x;
- \\}
- , "");
- case.addCompareOutput(
- \\const Point = struct { x: i32, y: i32, z: i32, a: i32, b: i32 };
- \\pub export fn main() c_int {
- \\ var p: Point = .{
- \\ .x = 18,
- \\ .y = 24,
- \\ .z = 1,
- \\ .a = 2,
- \\ .b = 3,
- \\ };
- \\ return p.y - p.x - p.z - p.a - p.b;
- \\}
- , "");
- }
-
- {
- var case = ctx.exeFromCompiledC("unions", .{}, b);
-
- case.addError(
- \\const U = union {
- \\ a: u32,
- \\ b
- \\};
- , &.{
- ":3:5: error: union field missing type",
- });
-
- case.addError(
- \\const E = enum { a, b };
- \\const U = union(E) {
- \\ a: u32 = 1,
- \\ b: f32 = 2,
- \\};
- , &.{
- ":2:11: error: explicitly valued tagged union requires inferred enum tag type",
- ":3:14: note: tag value specified here",
- });
-
- case.addError(
- \\const U = union(enum) {
- \\ a: u32 = 1,
- \\ b: f32 = 2,
- \\};
- , &.{
- ":1:11: error: explicitly valued tagged union missing integer tag type",
- ":2:14: note: tag value specified here",
- });
- }
-
- {
- var case = ctx.exeFromCompiledC("enums", .{}, b);
-
- case.addError(
- \\const E1 = packed enum { a, b, c };
- \\const E2 = extern enum { a, b, c };
- \\export fn foo() void {
- \\ _ = E1.a;
- \\}
- \\export fn bar() void {
- \\ _ = E2.a;
- \\}
- , &.{
- ":1:12: error: enums do not support 'packed' or 'extern'; instead provide an explicit integer tag type",
- ":2:12: error: enums do not support 'packed' or 'extern'; instead provide an explicit integer tag type",
- });
-
- // comptime and types are caught in AstGen.
- case.addError(
- \\const E1 = enum {
- \\ a,
- \\ comptime b,
- \\ c,
- \\};
- \\const E2 = enum {
- \\ a,
- \\ b: i32,
- \\ c,
- \\};
- \\export fn foo() void {
- \\ _ = E1.a;
- \\}
- \\export fn bar() void {
- \\ _ = E2.a;
- \\}
- , &.{
- ":3:5: error: enum fields cannot be marked comptime",
- ":8:8: error: enum fields do not have types",
- ":6:12: note: consider 'union(enum)' here to make it a tagged union",
- });
-
- // @intFromEnum, @enumFromInt, enum literal coercion, field access syntax, comparison, switch
- case.addCompareOutput(
- \\const Number = enum { One, Two, Three };
- \\
- \\pub export fn main() c_int {
- \\ var number1 = Number.One;
- \\ var number2: Number = .Two;
- \\ const number3: Number = @enumFromInt(2);
- \\ if (number1 == number2) return 1;
- \\ if (number2 == number3) return 1;
- \\ if (@intFromEnum(number1) != 0) return 1;
- \\ if (@intFromEnum(number2) != 1) return 1;
- \\ if (@intFromEnum(number3) != 2) return 1;
- \\ var x: Number = .Two;
- \\ if (number2 != x) return 1;
- \\ switch (x) {
- \\ .One => return 1,
- \\ .Two => return 0,
- \\ number3 => return 2,
- \\ }
- \\}
- , "");
-
- // Specifying alignment is a parse error.
- // This also tests going from a successful build to a parse error.
- case.addError(
- \\const E1 = enum {
- \\ a,
- \\ b align(4),
- \\ c,
- \\};
- \\export fn foo() void {
- \\ _ = E1.a;
- \\}
- , &.{
- ":3:13: error: enum fields cannot be aligned",
- });
-
- // Redundant non-exhaustive enum mark.
- // This also tests going from a parse error to an AstGen error.
- case.addError(
- \\const E1 = enum {
- \\ a,
- \\ _,
- \\ b,
- \\ c,
- \\ _,
- \\};
- \\export fn foo() void {
- \\ _ = E1.a;
- \\}
- , &.{
- ":6:5: error: redundant non-exhaustive enum mark",
- ":3:5: note: other mark here",
- });
-
- case.addError(
- \\const E1 = enum {
- \\ a,
- \\ b,
- \\ c,
- \\ _ = 10,
- \\};
- \\export fn foo() void {
- \\ _ = E1.a;
- \\}
- , &.{
- ":5:9: error: '_' is used to mark an enum as non-exhaustive and cannot be assigned a value",
- });
-
- case.addError(
- \\const E1 = enum { a, b, _ };
- \\export fn foo() void {
- \\ _ = E1.a;
- \\}
- , &.{
- ":1:12: error: non-exhaustive enum missing integer tag type",
- ":1:25: note: marked non-exhaustive here",
- });
-
- case.addError(
- \\const E1 = enum { a, b, c, b, d };
- \\pub export fn main() c_int {
- \\ _ = E1.a;
- \\}
- , &.{
- ":1:22: error: duplicate enum field name",
- ":1:28: note: duplicate field here",
- ":1:12: note: enum declared here",
- });
-
- case.addError(
- \\pub export fn main() c_int {
- \\ const a = true;
- \\ _ = @intFromEnum(a);
- \\}
- , &.{
- ":3:20: error: expected enum or tagged union, found 'bool'",
- });
-
- case.addError(
- \\pub export fn main() c_int {
- \\ const a = 1;
- \\ _ = @as(bool, @enumFromInt(a));
- \\}
- , &.{
- ":3:19: error: expected enum, found 'bool'",
- });
-
- case.addError(
- \\const E = enum { a, b, c };
- \\pub export fn main() c_int {
- \\ _ = @as(E, @enumFromInt(3));
- \\}
- , &.{
- ":3:16: error: enum 'tmp.E' has no tag with value '3'",
- ":1:11: note: enum declared here",
- });
-
- case.addError(
- \\const E = enum { a, b, c };
- \\pub export fn main() c_int {
- \\ var x: E = .a;
- \\ switch (x) {
- \\ .a => {},
- \\ .c => {},
- \\ }
- \\}
- , &.{
- ":4:5: error: switch must handle all possibilities",
- ":1:21: note: unhandled enumeration value: 'b'",
- ":1:11: note: enum 'tmp.E' declared here",
- });
-
- case.addError(
- \\const E = enum { a, b, c };
- \\pub export fn main() c_int {
- \\ var x: E = .a;
- \\ switch (x) {
- \\ .a => {},
- \\ .b => {},
- \\ .b => {},
- \\ .c => {},
- \\ }
- \\}
- , &.{
- ":7:10: error: duplicate switch value",
- ":6:10: note: previous value here",
- });
-
- case.addError(
- \\const E = enum { a, b, c };
- \\pub export fn main() c_int {
- \\ var x: E = .a;
- \\ switch (x) {
- \\ .a => {},
- \\ .b => {},
- \\ .c => {},
- \\ else => {},
- \\ }
- \\}
- , &.{
- ":8:14: error: unreachable else prong; all cases already handled",
- });
-
- case.addError(
- \\const E = enum { a, b, c };
- \\pub export fn main() c_int {
- \\ var x: E = .a;
- \\ switch (x) {
- \\ .a => {},
- \\ .b => {},
- \\ _ => {},
- \\ }
- \\}
- , &.{
- ":4:5: error: '_' prong only allowed when switching on non-exhaustive enums",
- ":7:11: note: '_' prong here",
- });
-
- case.addError(
- \\const E = enum { a, b, c };
- \\pub export fn main() c_int {
- \\ _ = E.d;
- \\}
- , &.{
- ":3:11: error: enum 'tmp.E' has no member named 'd'",
- ":1:11: note: enum declared here",
- });
-
- case.addError(
- \\const E = enum { a, b, c };
- \\pub export fn main() c_int {
- \\ var x: E = .d;
- \\ _ = x;
- \\}
- , &.{
- ":3:17: error: no field named 'd' in enum 'tmp.E'",
- ":1:11: note: enum declared here",
- });
- }
-
- {
- var case = ctx.exeFromCompiledC("shift right and left", .{}, b);
- case.addCompareOutput(
- \\pub export fn main() c_int {
- \\ var i: u32 = 16;
- \\ assert(i >> 1, 8);
- \\ return 0;
- \\}
- \\fn assert(a: u32, b: u32) void {
- \\ if (a != b) unreachable;
- \\}
- , "");
-
- case.addCompareOutput(
- \\pub export fn main() c_int {
- \\ var i: u32 = 16;
- \\ assert(i << 1, 32);
- \\ return 0;
- \\}
- \\fn assert(a: u32, b: u32) void {
- \\ if (a != b) unreachable;
- \\}
- , "");
- }
-
- {
- var case = ctx.exeFromCompiledC("inferred error sets", .{}, b);
-
- case.addCompareOutput(
- \\pub export fn main() c_int {
- \\ if (foo()) |_| {
- \\ @panic("test fail");
- \\ } else |err| {
- \\ if (err != error.ItBroke) {
- \\ @panic("test fail");
- \\ }
- \\ }
- \\ return 0;
- \\}
- \\fn foo() !void {
- \\ return error.ItBroke;
- \\}
- , "");
- }
-
- {
- // TODO: add u64 tests, ran into issues with the literal generated for std.math.maxInt(u64)
- var case = ctx.exeFromCompiledC("add and sub wrapping operations", .{}, b);
- case.addCompareOutput(
- \\pub export fn main() c_int {
- \\ // Addition
- \\ if (!add_u3(1, 1, 2)) return 1;
- \\ if (!add_u3(7, 1, 0)) return 1;
- \\ if (!add_i3(1, 1, 2)) return 1;
- \\ if (!add_i3(3, 2, -3)) return 1;
- \\ if (!add_i3(-3, -2, 3)) return 1;
- \\ if (!add_c_int(1, 1, 2)) return 1;
- \\ // TODO enable these when stage2 supports std.math.maxInt
- \\ //if (!add_c_int(maxInt(c_int), 2, minInt(c_int) + 1)) return 1;
- \\ //if (!add_c_int(maxInt(c_int) + 1, -2, maxInt(c_int))) return 1;
- \\
- \\ // Subtraction
- \\ if (!sub_u3(2, 1, 1)) return 1;
- \\ if (!sub_u3(0, 1, 7)) return 1;
- \\ if (!sub_i3(2, 1, 1)) return 1;
- \\ if (!sub_i3(3, -2, -3)) return 1;
- \\ if (!sub_i3(-3, 2, 3)) return 1;
- \\ if (!sub_c_int(2, 1, 1)) return 1;
- \\ // TODO enable these when stage2 supports std.math.maxInt
- \\ //if (!sub_c_int(maxInt(c_int), -2, minInt(c_int) + 1)) return 1;
- \\ //if (!sub_c_int(minInt(c_int) + 1, 2, maxInt(c_int))) return 1;
- \\
- \\ return 0;
- \\}
- \\fn add_u3(lhs: u3, rhs: u3, expected: u3) bool {
- \\ return expected == lhs +% rhs;
- \\}
- \\fn add_i3(lhs: i3, rhs: i3, expected: i3) bool {
- \\ return expected == lhs +% rhs;
- \\}
- \\fn add_c_int(lhs: c_int, rhs: c_int, expected: c_int) bool {
- \\ return expected == lhs +% rhs;
- \\}
- \\fn sub_u3(lhs: u3, rhs: u3, expected: u3) bool {
- \\ return expected == lhs -% rhs;
- \\}
- \\fn sub_i3(lhs: i3, rhs: i3, expected: i3) bool {
- \\ return expected == lhs -% rhs;
- \\}
- \\fn sub_c_int(lhs: c_int, rhs: c_int, expected: c_int) bool {
- \\ return expected == lhs -% rhs;
- \\}
- , "");
- }
-
- {
- var case = ctx.exeFromCompiledC("rem", linux_x64, b);
- case.addCompareOutput(
- \\fn assert(ok: bool) void {
- \\ if (!ok) unreachable;
- \\}
- \\fn rem(lhs: i32, rhs: i32, expected: i32) bool {
- \\ return @rem(lhs, rhs) == expected;
- \\}
- \\pub export fn main() c_int {
- \\ assert(rem(-5, 3, -2));
- \\ assert(rem(5, 3, 2));
- \\ return 0;
- \\}
- , "");
- }
-}