From 588b88b98753f02061e562a9c15c2396bcd95dee Mon Sep 17 00:00:00 2001 From: Luuk de Gram Date: Thu, 3 Feb 2022 22:25:46 +0100 Subject: Move passing behavior tests Singular tests (such as in the bug ones) are moved to top level with exclusions for non-passing backends. The big behavior tests such as array_llvm and slice are moved to the inner scope with the C backend disabled. They all pass for the wasm backend now --- test/behavior/array_llvm.zig | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'test/behavior/array_llvm.zig') diff --git a/test/behavior/array_llvm.zig b/test/behavior/array_llvm.zig index 5be5974fff..c3df5ba837 100644 --- a/test/behavior/array_llvm.zig +++ b/test/behavior/array_llvm.zig @@ -7,6 +7,7 @@ var s_array: [8]Sub = undefined; const Sub = struct { b: u8 }; const Str = struct { a: []Sub }; test "set global var array via slice embedded in struct" { + if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; // TODO var s = Str{ .a = s_array[0..] }; s.a[0].b = 1; @@ -19,6 +20,7 @@ test "set global var array via slice embedded in struct" { } test "read/write through global variable array of struct fields initialized via array mult" { + if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; // TODO const S = struct { fn doTheTest() !void { try expect(storage[0].term == 1); @@ -36,6 +38,7 @@ test "read/write through global variable array of struct fields initialized via } test "implicit cast single-item pointer" { + if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; // TODO try testImplicitCastSingleItemPtr(); comptime try testImplicitCastSingleItemPtr(); } @@ -52,6 +55,7 @@ fn testArrayByValAtComptime(b: [2]u8) u8 { } test "comptime evaluating function that takes array by value" { + if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; // TODO const arr = [_]u8{ 1, 2 }; const x = comptime testArrayByValAtComptime(arr); const y = comptime testArrayByValAtComptime(arr); @@ -60,12 +64,14 @@ test "comptime evaluating function that takes array by value" { } test "runtime initialize array elem and then implicit cast to slice" { + if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; // TODO var two: i32 = 2; const x: []const i32 = &[_]i32{two}; try expect(x[0] == 2); } test "array literal as argument to function" { + if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; // TODO const S = struct { fn entry(two: i32) !void { try foo(&[_]i32{ 1, 2, 3 }); @@ -90,6 +96,7 @@ test "array literal as argument to function" { } test "double nested array to const slice cast in array literal" { + if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; // TODO const S = struct { fn entry(two: i32) !void { const cases = [_][]const []const i32{ @@ -147,6 +154,7 @@ test "double nested array to const slice cast in array literal" { } test "anonymous literal in array" { + if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; // TODO const S = struct { const Foo = struct { a: usize = 2, @@ -168,6 +176,7 @@ test "anonymous literal in array" { } test "access the null element of a null terminated array" { + if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; // TODO const S = struct { fn doTheTest() !void { var array: [4:0]u8 = .{ 'a', 'o', 'e', 'u' }; @@ -181,6 +190,7 @@ test "access the null element of a null terminated array" { } test "type deduction for array subscript expression" { + if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; // TODO const S = struct { fn doTheTest() !void { var array = [_]u8{ 0x55, 0xAA }; @@ -196,6 +206,8 @@ test "type deduction for array subscript expression" { test "sentinel element count towards the ABI size calculation" { if (@import("builtin").zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO + if (@import("builtin").zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO + if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; // TODO const S = struct { fn doTheTest() !void { @@ -218,6 +230,8 @@ test "sentinel element count towards the ABI size calculation" { test "zero-sized array with recursive type definition" { if (@import("builtin").zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO + if (@import("builtin").zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO + if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; // TODO const U = struct { fn foo(comptime T: type, comptime n: usize) type { @@ -237,6 +251,7 @@ test "zero-sized array with recursive type definition" { } test "type coercion of anon struct literal to array" { + if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; // TODO const S = struct { const U = union { a: u32, @@ -253,6 +268,7 @@ test "type coercion of anon struct literal to array" { try expect(arr1[2] == 54); if (@import("builtin").zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO + if (@import("builtin").zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO var x2: U = .{ .a = 42 }; const t2 = .{ x2, .{ .b = true }, .{ .c = "hello" } }; @@ -268,6 +284,8 @@ test "type coercion of anon struct literal to array" { test "type coercion of pointer to anon struct literal to pointer to array" { if (@import("builtin").zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO + if (@import("builtin").zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO + if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; // TODO const S = struct { const U = union { -- cgit v1.2.3 From c349191b75811f8a21e26f8b175483449fae1638 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 12 Feb 2022 21:13:07 -0700 Subject: organize behavior tests moving towards disabling failing tests on an individual basis --- test/behavior.zig | 7 - test/behavior/array.zig | 350 +++++++++++ test/behavior/array_llvm.zig | 315 ---------- test/behavior/cast.zig | 340 ++++++++++- test/behavior/cast_llvm.zig | 299 ---------- test/behavior/error.zig | 26 + test/behavior/error_llvm.zig | 24 - test/behavior/sizeof_and_typeof.zig | 113 ++++ test/behavior/sizeof_and_typeof_stage1.zig | 105 ---- test/behavior/struct.zig | 894 ++++++++++++++++++++++++++++- test/behavior/struct_llvm.zig | 802 -------------------------- test/behavior/truncate.zig | 13 + test/behavior/truncate_stage1.zig | 13 - test/behavior/type.zig | 386 +++++++++++++ test/behavior/type_stage1.zig | 362 ------------ 15 files changed, 2111 insertions(+), 1938 deletions(-) delete mode 100644 test/behavior/array_llvm.zig delete mode 100644 test/behavior/cast_llvm.zig delete mode 100644 test/behavior/error_llvm.zig delete mode 100644 test/behavior/sizeof_and_typeof_stage1.zig delete mode 100644 test/behavior/struct_llvm.zig delete mode 100644 test/behavior/truncate_stage1.zig delete mode 100644 test/behavior/type_stage1.zig (limited to 'test/behavior/array_llvm.zig') diff --git a/test/behavior.zig b/test/behavior.zig index 8188f2baaa..404ce376a2 100644 --- a/test/behavior.zig +++ b/test/behavior.zig @@ -46,7 +46,6 @@ test { if (builtin.zig_backend != .stage2_arm and builtin.zig_backend != .stage2_x86_64) { // Tests that pass (partly) for stage1, llvm backend, C backend, wasm backend. - _ = @import("behavior/array_llvm.zig"); _ = @import("behavior/bitcast.zig"); _ = @import("behavior/bugs/624.zig"); _ = @import("behavior/bugs/704.zig"); @@ -61,7 +60,6 @@ test { _ = @import("behavior/bugs/4954.zig"); _ = @import("behavior/byval_arg_var.zig"); _ = @import("behavior/call.zig"); - _ = @import("behavior/cast_llvm.zig"); _ = @import("behavior/defer.zig"); _ = @import("behavior/enum.zig"); _ = @import("behavior/error.zig"); @@ -98,7 +96,6 @@ test { // Tests that pass for stage1 and the llvm backend. _ = @import("behavior/atomics.zig"); _ = @import("behavior/bugs/9584.zig"); - _ = @import("behavior/error_llvm.zig"); _ = @import("behavior/eval.zig"); _ = @import("behavior/floatop.zig"); _ = @import("behavior/math.zig"); @@ -107,7 +104,6 @@ test { _ = @import("behavior/popcount.zig"); _ = @import("behavior/saturating_arithmetic.zig"); _ = @import("behavior/sizeof_and_typeof.zig"); - _ = @import("behavior/struct_llvm.zig"); _ = @import("behavior/switch.zig"); _ = @import("behavior/widening.zig"); @@ -156,14 +152,11 @@ test { _ = @import("behavior/reflection.zig"); _ = @import("behavior/select.zig"); _ = @import("behavior/shuffle.zig"); - _ = @import("behavior/sizeof_and_typeof_stage1.zig"); _ = @import("behavior/struct_contains_null_ptr_itself.zig"); _ = @import("behavior/struct_contains_slice_of_itself.zig"); _ = @import("behavior/switch_prong_err_enum.zig"); _ = @import("behavior/switch_prong_implicit_cast.zig"); - _ = @import("behavior/truncate_stage1.zig"); _ = @import("behavior/tuple.zig"); - _ = @import("behavior/type_stage1.zig"); _ = @import("behavior/typename.zig"); _ = @import("behavior/union_with_members.zig"); _ = @import("behavior/var_args.zig"); diff --git a/test/behavior/array.zig b/test/behavior/array.zig index 0450d0781b..23820e71b5 100644 --- a/test/behavior/array.zig +++ b/test/behavior/array.zig @@ -222,3 +222,353 @@ test "anonymous list literal syntax" { try S.doTheTest(); comptime try S.doTheTest(); } + +var s_array: [8]Sub = undefined; +const Sub = struct { b: u8 }; +const Str = struct { a: []Sub }; +test "set global var array via slice embedded in struct" { + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + + var s = Str{ .a = s_array[0..] }; + + s.a[0].b = 1; + s.a[1].b = 2; + s.a[2].b = 3; + + try expect(s_array[0].b == 1); + try expect(s_array[1].b == 2); + try expect(s_array[2].b == 3); +} + +test "read/write through global variable array of struct fields initialized via array mult" { + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + + const S = struct { + fn doTheTest() !void { + try expect(storage[0].term == 1); + storage[0] = MyStruct{ .term = 123 }; + try expect(storage[0].term == 123); + } + + pub const MyStruct = struct { + term: usize, + }; + + var storage: [1]MyStruct = [_]MyStruct{MyStruct{ .term = 1 }} ** 1; + }; + try S.doTheTest(); +} + +test "implicit cast single-item pointer" { + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + + try testImplicitCastSingleItemPtr(); + comptime try testImplicitCastSingleItemPtr(); +} + +fn testImplicitCastSingleItemPtr() !void { + var byte: u8 = 100; + const slice = @as(*[1]u8, &byte)[0..]; + slice[0] += 1; + try expect(byte == 101); +} + +fn testArrayByValAtComptime(b: [2]u8) u8 { + return b[0]; +} + +test "comptime evaluating function that takes array by value" { + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + + const arr = [_]u8{ 1, 2 }; + const x = comptime testArrayByValAtComptime(arr); + const y = comptime testArrayByValAtComptime(arr); + try expect(x == 1); + try expect(y == 1); +} + +test "runtime initialize array elem and then implicit cast to slice" { + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + + var two: i32 = 2; + const x: []const i32 = &[_]i32{two}; + try expect(x[0] == 2); +} + +test "array literal as argument to function" { + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + + const S = struct { + fn entry(two: i32) !void { + try foo(&[_]i32{ 1, 2, 3 }); + try foo(&[_]i32{ 1, two, 3 }); + try foo2(true, &[_]i32{ 1, 2, 3 }); + try foo2(true, &[_]i32{ 1, two, 3 }); + } + fn foo(x: []const i32) !void { + try expect(x[0] == 1); + try expect(x[1] == 2); + try expect(x[2] == 3); + } + fn foo2(trash: bool, x: []const i32) !void { + try expect(trash); + try expect(x[0] == 1); + try expect(x[1] == 2); + try expect(x[2] == 3); + } + }; + try S.entry(2); + comptime try S.entry(2); +} + +test "double nested array to const slice cast in array literal" { + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + + const S = struct { + fn entry(two: i32) !void { + const cases = [_][]const []const i32{ + &[_][]const i32{&[_]i32{1}}, + &[_][]const i32{&[_]i32{ 2, 3 }}, + &[_][]const i32{ + &[_]i32{4}, + &[_]i32{ 5, 6, 7 }, + }, + }; + try check(&cases); + + const cases2 = [_][]const i32{ + &[_]i32{1}, + &[_]i32{ two, 3 }, + }; + try expect(cases2.len == 2); + try expect(cases2[0].len == 1); + try expect(cases2[0][0] == 1); + try expect(cases2[1].len == 2); + try expect(cases2[1][0] == 2); + try expect(cases2[1][1] == 3); + + const cases3 = [_][]const []const i32{ + &[_][]const i32{&[_]i32{1}}, + &[_][]const i32{&[_]i32{ two, 3 }}, + &[_][]const i32{ + &[_]i32{4}, + &[_]i32{ 5, 6, 7 }, + }, + }; + try check(&cases3); + } + + fn check(cases: []const []const []const i32) !void { + try expect(cases.len == 3); + try expect(cases[0].len == 1); + try expect(cases[0][0].len == 1); + try expect(cases[0][0][0] == 1); + try expect(cases[1].len == 1); + try expect(cases[1][0].len == 2); + try expect(cases[1][0][0] == 2); + try expect(cases[1][0][1] == 3); + try expect(cases[2].len == 2); + try expect(cases[2][0].len == 1); + try expect(cases[2][0][0] == 4); + try expect(cases[2][1].len == 3); + try expect(cases[2][1][0] == 5); + try expect(cases[2][1][1] == 6); + try expect(cases[2][1][2] == 7); + } + }; + try S.entry(2); + comptime try S.entry(2); +} + +test "anonymous literal in array" { + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + + const S = struct { + const Foo = struct { + a: usize = 2, + b: usize = 4, + }; + fn doTheTest() !void { + var array: [2]Foo = .{ + .{ .a = 3 }, + .{ .b = 3 }, + }; + try expect(array[0].a == 3); + try expect(array[0].b == 4); + try expect(array[1].a == 2); + try expect(array[1].b == 3); + } + }; + try S.doTheTest(); + comptime try S.doTheTest(); +} + +test "access the null element of a null terminated array" { + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + + const S = struct { + fn doTheTest() !void { + var array: [4:0]u8 = .{ 'a', 'o', 'e', 'u' }; + try expect(array[4] == 0); + var len: usize = 4; + try expect(array[len] == 0); + } + }; + try S.doTheTest(); + comptime try S.doTheTest(); +} + +test "type deduction for array subscript expression" { + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + + const S = struct { + fn doTheTest() !void { + var array = [_]u8{ 0x55, 0xAA }; + var v0 = true; + try expect(@as(u8, 0xAA) == array[if (v0) 1 else 0]); + var v1 = false; + try expect(@as(u8, 0x55) == array[if (v1) 1 else 0]); + } + }; + try S.doTheTest(); + comptime try S.doTheTest(); +} + +test "sentinel element count towards the ABI size calculation" { + if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + + const S = struct { + fn doTheTest() !void { + const T = packed struct { + fill_pre: u8 = 0x55, + data: [0:0]u8 = undefined, + fill_post: u8 = 0xAA, + }; + var x = T{}; + var as_slice = mem.asBytes(&x); + try expect(@as(usize, 3) == as_slice.len); + try expect(@as(u8, 0x55) == as_slice[0]); + try expect(@as(u8, 0xAA) == as_slice[2]); + } + }; + + try S.doTheTest(); + comptime try S.doTheTest(); +} + +test "zero-sized array with recursive type definition" { + if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + + const U = struct { + fn foo(comptime T: type, comptime n: usize) type { + return struct { + s: [n]T, + x: usize = n, + }; + } + }; + + const S = struct { + list: U.foo(@This(), 0), + }; + + var t: S = .{ .list = .{ .s = undefined } }; + try expect(@as(usize, 0) == t.list.x); +} + +test "type coercion of anon struct literal to array" { + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + + const S = struct { + const U = union { + a: u32, + b: bool, + c: []const u8, + }; + + fn doTheTest() !void { + var x1: u8 = 42; + const t1 = .{ x1, 56, 54 }; + var arr1: [3]u8 = t1; + try expect(arr1[0] == 42); + try expect(arr1[1] == 56); + try expect(arr1[2] == 54); + + if (@import("builtin").zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO + if (@import("builtin").zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO + + var x2: U = .{ .a = 42 }; + const t2 = .{ x2, .{ .b = true }, .{ .c = "hello" } }; + var arr2: [3]U = t2; + try expect(arr2[0].a == 42); + try expect(arr2[1].b == true); + try expect(mem.eql(u8, arr2[2].c, "hello")); + } + }; + try S.doTheTest(); + comptime try S.doTheTest(); +} + +test "type coercion of pointer to anon struct literal to pointer to array" { + if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + + const S = struct { + const U = union { + a: u32, + b: bool, + c: []const u8, + }; + + fn doTheTest() !void { + var x1: u8 = 42; + const t1 = &.{ x1, 56, 54 }; + var arr1: *const [3]u8 = t1; + try expect(arr1[0] == 42); + try expect(arr1[1] == 56); + try expect(arr1[2] == 54); + + var x2: U = .{ .a = 42 }; + const t2 = &.{ x2, .{ .b = true }, .{ .c = "hello" } }; + var arr2: *const [3]U = t2; + try expect(arr2[0].a == 42); + try expect(arr2[1].b == true); + try expect(mem.eql(u8, arr2[2].c, "hello")); + } + }; + try S.doTheTest(); + comptime try S.doTheTest(); +} diff --git a/test/behavior/array_llvm.zig b/test/behavior/array_llvm.zig deleted file mode 100644 index c3df5ba837..0000000000 --- a/test/behavior/array_llvm.zig +++ /dev/null @@ -1,315 +0,0 @@ -const std = @import("std"); -const testing = std.testing; -const expect = testing.expect; -const mem = std.mem; - -var s_array: [8]Sub = undefined; -const Sub = struct { b: u8 }; -const Str = struct { a: []Sub }; -test "set global var array via slice embedded in struct" { - if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; // TODO - var s = Str{ .a = s_array[0..] }; - - s.a[0].b = 1; - s.a[1].b = 2; - s.a[2].b = 3; - - try expect(s_array[0].b == 1); - try expect(s_array[1].b == 2); - try expect(s_array[2].b == 3); -} - -test "read/write through global variable array of struct fields initialized via array mult" { - if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; // TODO - const S = struct { - fn doTheTest() !void { - try expect(storage[0].term == 1); - storage[0] = MyStruct{ .term = 123 }; - try expect(storage[0].term == 123); - } - - pub const MyStruct = struct { - term: usize, - }; - - var storage: [1]MyStruct = [_]MyStruct{MyStruct{ .term = 1 }} ** 1; - }; - try S.doTheTest(); -} - -test "implicit cast single-item pointer" { - if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; // TODO - try testImplicitCastSingleItemPtr(); - comptime try testImplicitCastSingleItemPtr(); -} - -fn testImplicitCastSingleItemPtr() !void { - var byte: u8 = 100; - const slice = @as(*[1]u8, &byte)[0..]; - slice[0] += 1; - try expect(byte == 101); -} - -fn testArrayByValAtComptime(b: [2]u8) u8 { - return b[0]; -} - -test "comptime evaluating function that takes array by value" { - if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; // TODO - const arr = [_]u8{ 1, 2 }; - const x = comptime testArrayByValAtComptime(arr); - const y = comptime testArrayByValAtComptime(arr); - try expect(x == 1); - try expect(y == 1); -} - -test "runtime initialize array elem and then implicit cast to slice" { - if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; // TODO - var two: i32 = 2; - const x: []const i32 = &[_]i32{two}; - try expect(x[0] == 2); -} - -test "array literal as argument to function" { - if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; // TODO - const S = struct { - fn entry(two: i32) !void { - try foo(&[_]i32{ 1, 2, 3 }); - try foo(&[_]i32{ 1, two, 3 }); - try foo2(true, &[_]i32{ 1, 2, 3 }); - try foo2(true, &[_]i32{ 1, two, 3 }); - } - fn foo(x: []const i32) !void { - try expect(x[0] == 1); - try expect(x[1] == 2); - try expect(x[2] == 3); - } - fn foo2(trash: bool, x: []const i32) !void { - try expect(trash); - try expect(x[0] == 1); - try expect(x[1] == 2); - try expect(x[2] == 3); - } - }; - try S.entry(2); - comptime try S.entry(2); -} - -test "double nested array to const slice cast in array literal" { - if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; // TODO - const S = struct { - fn entry(two: i32) !void { - const cases = [_][]const []const i32{ - &[_][]const i32{&[_]i32{1}}, - &[_][]const i32{&[_]i32{ 2, 3 }}, - &[_][]const i32{ - &[_]i32{4}, - &[_]i32{ 5, 6, 7 }, - }, - }; - try check(&cases); - - const cases2 = [_][]const i32{ - &[_]i32{1}, - &[_]i32{ two, 3 }, - }; - try expect(cases2.len == 2); - try expect(cases2[0].len == 1); - try expect(cases2[0][0] == 1); - try expect(cases2[1].len == 2); - try expect(cases2[1][0] == 2); - try expect(cases2[1][1] == 3); - - const cases3 = [_][]const []const i32{ - &[_][]const i32{&[_]i32{1}}, - &[_][]const i32{&[_]i32{ two, 3 }}, - &[_][]const i32{ - &[_]i32{4}, - &[_]i32{ 5, 6, 7 }, - }, - }; - try check(&cases3); - } - - fn check(cases: []const []const []const i32) !void { - try expect(cases.len == 3); - try expect(cases[0].len == 1); - try expect(cases[0][0].len == 1); - try expect(cases[0][0][0] == 1); - try expect(cases[1].len == 1); - try expect(cases[1][0].len == 2); - try expect(cases[1][0][0] == 2); - try expect(cases[1][0][1] == 3); - try expect(cases[2].len == 2); - try expect(cases[2][0].len == 1); - try expect(cases[2][0][0] == 4); - try expect(cases[2][1].len == 3); - try expect(cases[2][1][0] == 5); - try expect(cases[2][1][1] == 6); - try expect(cases[2][1][2] == 7); - } - }; - try S.entry(2); - comptime try S.entry(2); -} - -test "anonymous literal in array" { - if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; // TODO - const S = struct { - const Foo = struct { - a: usize = 2, - b: usize = 4, - }; - fn doTheTest() !void { - var array: [2]Foo = .{ - .{ .a = 3 }, - .{ .b = 3 }, - }; - try expect(array[0].a == 3); - try expect(array[0].b == 4); - try expect(array[1].a == 2); - try expect(array[1].b == 3); - } - }; - try S.doTheTest(); - comptime try S.doTheTest(); -} - -test "access the null element of a null terminated array" { - if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; // TODO - const S = struct { - fn doTheTest() !void { - var array: [4:0]u8 = .{ 'a', 'o', 'e', 'u' }; - try expect(array[4] == 0); - var len: usize = 4; - try expect(array[len] == 0); - } - }; - try S.doTheTest(); - comptime try S.doTheTest(); -} - -test "type deduction for array subscript expression" { - if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; // TODO - const S = struct { - fn doTheTest() !void { - var array = [_]u8{ 0x55, 0xAA }; - var v0 = true; - try expect(@as(u8, 0xAA) == array[if (v0) 1 else 0]); - var v1 = false; - try expect(@as(u8, 0x55) == array[if (v1) 1 else 0]); - } - }; - try S.doTheTest(); - comptime try S.doTheTest(); -} - -test "sentinel element count towards the ABI size calculation" { - if (@import("builtin").zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO - if (@import("builtin").zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO - if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; // TODO - - const S = struct { - fn doTheTest() !void { - const T = packed struct { - fill_pre: u8 = 0x55, - data: [0:0]u8 = undefined, - fill_post: u8 = 0xAA, - }; - var x = T{}; - var as_slice = mem.asBytes(&x); - try expect(@as(usize, 3) == as_slice.len); - try expect(@as(u8, 0x55) == as_slice[0]); - try expect(@as(u8, 0xAA) == as_slice[2]); - } - }; - - try S.doTheTest(); - comptime try S.doTheTest(); -} - -test "zero-sized array with recursive type definition" { - if (@import("builtin").zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO - if (@import("builtin").zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO - if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; // TODO - - const U = struct { - fn foo(comptime T: type, comptime n: usize) type { - return struct { - s: [n]T, - x: usize = n, - }; - } - }; - - const S = struct { - list: U.foo(@This(), 0), - }; - - var t: S = .{ .list = .{ .s = undefined } }; - try expect(@as(usize, 0) == t.list.x); -} - -test "type coercion of anon struct literal to array" { - if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; // TODO - const S = struct { - const U = union { - a: u32, - b: bool, - c: []const u8, - }; - - fn doTheTest() !void { - var x1: u8 = 42; - const t1 = .{ x1, 56, 54 }; - var arr1: [3]u8 = t1; - try expect(arr1[0] == 42); - try expect(arr1[1] == 56); - try expect(arr1[2] == 54); - - if (@import("builtin").zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO - if (@import("builtin").zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO - - var x2: U = .{ .a = 42 }; - const t2 = .{ x2, .{ .b = true }, .{ .c = "hello" } }; - var arr2: [3]U = t2; - try expect(arr2[0].a == 42); - try expect(arr2[1].b == true); - try expect(mem.eql(u8, arr2[2].c, "hello")); - } - }; - try S.doTheTest(); - comptime try S.doTheTest(); -} - -test "type coercion of pointer to anon struct literal to pointer to array" { - if (@import("builtin").zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO - if (@import("builtin").zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO - if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; // TODO - - const S = struct { - const U = union { - a: u32, - b: bool, - c: []const u8, - }; - - fn doTheTest() !void { - var x1: u8 = 42; - const t1 = &.{ x1, 56, 54 }; - var arr1: *const [3]u8 = t1; - try expect(arr1[0] == 42); - try expect(arr1[1] == 56); - try expect(arr1[2] == 54); - - var x2: U = .{ .a = 42 }; - const t2 = &.{ x2, .{ .b = true }, .{ .c = "hello" } }; - var arr2: *const [3]U = t2; - try expect(arr2[0].a == 42); - try expect(arr2[1].b == true); - try expect(mem.eql(u8, arr2[2].c, "hello")); - } - }; - try S.doTheTest(); - comptime try S.doTheTest(); -} diff --git a/test/behavior/cast.zig b/test/behavior/cast.zig index 79f75f773c..4028d8c5f1 100644 --- a/test/behavior/cast.zig +++ b/test/behavior/cast.zig @@ -1,8 +1,9 @@ +const builtin = @import("builtin"); const std = @import("std"); const expect = std.testing.expect; const mem = std.mem; const maxInt = std.math.maxInt; -const builtin = @import("builtin"); +const native_endian = builtin.target.cpu.arch.endian(); test "int to ptr cast" { const x = @as(usize, 13); @@ -93,7 +94,8 @@ test "comptime_int @intToFloat" { } test "@floatToInt" { - if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO try testFloatToInts(); comptime try testFloatToInts(); @@ -802,3 +804,337 @@ test "comptime float casts" { try expectFloatToInt(comptime_int, 1234, i16, 1234); try expectFloatToInt(comptime_float, 12.3, comptime_int, 12); } + +test "pointer reinterpret const float to int" { + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + + // The hex representation is 0x3fe3333333333303. + const float: f64 = 5.99999999999994648725e-01; + const float_ptr = &float; + const int_ptr = @ptrCast(*const i32, float_ptr); + const int_val = int_ptr.*; + if (native_endian == .Little) + try expect(int_val == 0x33333303) + else + try expect(int_val == 0x3fe33333); +} + +test "implicit cast from [*]T to ?*anyopaque" { + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + + var a = [_]u8{ 3, 2, 1 }; + var runtime_zero: usize = 0; + incrementVoidPtrArray(a[runtime_zero..].ptr, 3); + try expect(std.mem.eql(u8, &a, &[_]u8{ 4, 3, 2 })); +} + +fn incrementVoidPtrArray(array: ?*anyopaque, len: usize) void { + var n: usize = 0; + while (n < len) : (n += 1) { + @ptrCast([*]u8, array.?)[n] += 1; + } +} + +test "compile time int to ptr of function" { + if (builtin.zig_backend == .stage1) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .aarch64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + + try foobar(FUNCTION_CONSTANT); +} + +pub const FUNCTION_CONSTANT = @intToPtr(PFN_void, maxInt(usize)); +pub const PFN_void = *const fn (*anyopaque) callconv(.C) void; + +fn foobar(func: PFN_void) !void { + try std.testing.expect(@ptrToInt(func) == maxInt(usize)); +} + +test "implicit ptr to *anyopaque" { + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + + var a: u32 = 1; + var ptr: *align(@alignOf(u32)) anyopaque = &a; + var b: *u32 = @ptrCast(*u32, ptr); + try expect(b.* == 1); + var ptr2: ?*align(@alignOf(u32)) anyopaque = &a; + var c: *u32 = @ptrCast(*u32, ptr2.?); + try expect(c.* == 1); +} + +test "return null from fn() anyerror!?&T" { + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + + const a = returnNullFromOptionalTypeErrorRef(); + const b = returnNullLitFromOptionalTypeErrorRef(); + try expect((try a) == null and (try b) == null); +} +fn returnNullFromOptionalTypeErrorRef() anyerror!?*A { + const a: ?*A = null; + return a; +} +fn returnNullLitFromOptionalTypeErrorRef() anyerror!?*A { + return null; +} + +test "peer type resolution: [0]u8 and []const u8" { + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + + try expect(peerTypeEmptyArrayAndSlice(true, "hi").len == 0); + try expect(peerTypeEmptyArrayAndSlice(false, "hi").len == 1); + comptime { + try expect(peerTypeEmptyArrayAndSlice(true, "hi").len == 0); + try expect(peerTypeEmptyArrayAndSlice(false, "hi").len == 1); + } +} +fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 { + if (a) { + return &[_]u8{}; + } + + return slice[0..1]; +} + +test "implicitly cast from [N]T to ?[]const T" { + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + + try expect(mem.eql(u8, castToOptionalSlice().?, "hi")); + comptime try expect(mem.eql(u8, castToOptionalSlice().?, "hi")); +} + +fn castToOptionalSlice() ?[]const u8 { + return "hi"; +} + +test "cast u128 to f128 and back" { + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + + comptime try testCast128(); + try testCast128(); +} + +fn testCast128() !void { + try expect(cast128Int(cast128Float(0x7fff0000000000000000000000000000)) == 0x7fff0000000000000000000000000000); +} + +fn cast128Int(x: f128) u128 { + return @bitCast(u128, x); +} + +fn cast128Float(x: u128) f128 { + return @bitCast(f128, x); +} + +test "implicit cast from *[N]T to ?[*]T" { + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + + var x: ?[*]u16 = null; + var y: [4]u16 = [4]u16{ 0, 1, 2, 3 }; + + x = &y; + try expect(std.mem.eql(u16, x.?[0..4], y[0..4])); + x.?[0] = 8; + y[3] = 6; + try expect(std.mem.eql(u16, x.?[0..4], y[0..4])); +} + +test "implicit cast from *T to ?*anyopaque" { + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + + var a: u8 = 1; + incrementVoidPtrValue(&a); + try std.testing.expect(a == 2); +} + +fn incrementVoidPtrValue(value: ?*anyopaque) void { + @ptrCast(*u8, value.?).* += 1; +} + +test "implicit cast *[0]T to E![]const u8" { + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + + var x = @as(anyerror![]const u8, &[0]u8{}); + try expect((x catch unreachable).len == 0); +} + +var global_array: [4]u8 = undefined; +test "cast from array reference to fn: comptime fn ptr" { + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + + const f = @ptrCast(*const fn () callconv(.C) void, &global_array); + try expect(@ptrToInt(f) == @ptrToInt(&global_array)); +} +test "cast from array reference to fn: runtime fn ptr" { + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + + var f = @ptrCast(*const fn () callconv(.C) void, &global_array); + try expect(@ptrToInt(f) == @ptrToInt(&global_array)); +} + +test "*const [N]null u8 to ?[]const u8" { + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + + const S = struct { + fn doTheTest() !void { + var a = "Hello"; + var b: ?[]const u8 = a; + try expect(mem.eql(u8, b.?, "Hello")); + } + }; + try S.doTheTest(); + comptime try S.doTheTest(); +} + +test "cast between [*c]T and ?[*:0]T on fn parameter" { + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + + const S = struct { + const Handler = ?fn ([*c]const u8) callconv(.C) void; + fn addCallback(handler: Handler) void { + _ = handler; + } + + fn myCallback(cstr: ?[*:0]const u8) callconv(.C) void { + _ = cstr; + } + + fn doTheTest() void { + addCallback(myCallback); + } + }; + S.doTheTest(); +} + +var global_struct: struct { f0: usize } = undefined; +test "assignment to optional pointer result loc" { + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + + var foo: struct { ptr: ?*anyopaque } = .{ .ptr = &global_struct }; + try expect(foo.ptr.? == @ptrCast(*anyopaque, &global_struct)); +} + +test "cast between *[N]void and []void" { + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + + var a: [4]void = undefined; + var b: []void = &a; + try expect(b.len == 4); +} + +test "peer resolve arrays of different size to const slice" { + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + + try expect(mem.eql(u8, boolToStr(true), "true")); + try expect(mem.eql(u8, boolToStr(false), "false")); + comptime try expect(mem.eql(u8, boolToStr(true), "true")); + comptime try expect(mem.eql(u8, boolToStr(false), "false")); +} +fn boolToStr(b: bool) []const u8 { + return if (b) "true" else "false"; +} + +test "cast f16 to wider types" { + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO + + const S = struct { + fn doTheTest() !void { + var x: f16 = 1234.0; + try expect(@as(f32, 1234.0) == x); + try expect(@as(f64, 1234.0) == x); + try expect(@as(f128, 1234.0) == x); + } + }; + try S.doTheTest(); + comptime try S.doTheTest(); +} + +test "cast f128 to narrower types" { + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO + + const S = struct { + fn doTheTest() !void { + var x: f128 = 1234.0; + try expect(@as(f16, 1234.0) == @floatCast(f16, x)); + try expect(@as(f32, 1234.0) == @floatCast(f32, x)); + try expect(@as(f64, 1234.0) == @floatCast(f64, x)); + } + }; + try S.doTheTest(); + comptime try S.doTheTest(); +} + +test "peer type resolution: unreachable, null, slice" { + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + + const S = struct { + fn doTheTest(num: usize, word: []const u8) !void { + const result = switch (num) { + 0 => null, + 1 => word, + else => unreachable, + }; + try expect(mem.eql(u8, result.?, "hi")); + } + }; + try S.doTheTest(1, "hi"); +} + +test "cast i8 fn call peers to i32 result" { + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + + const S = struct { + fn doTheTest() !void { + var cond = true; + const value: i32 = if (cond) smallBoi() else bigBoi(); + try expect(value == 123); + } + fn smallBoi() i8 { + return 123; + } + fn bigBoi() i16 { + return 1234; + } + }; + try S.doTheTest(); + comptime try S.doTheTest(); +} diff --git a/test/behavior/cast_llvm.zig b/test/behavior/cast_llvm.zig deleted file mode 100644 index 6f9b77b8f2..0000000000 --- a/test/behavior/cast_llvm.zig +++ /dev/null @@ -1,299 +0,0 @@ -const builtin = @import("builtin"); -const std = @import("std"); -const expect = std.testing.expect; -const mem = std.mem; -const maxInt = std.math.maxInt; -const native_endian = builtin.target.cpu.arch.endian(); - -test "pointer reinterpret const float to int" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO - - // The hex representation is 0x3fe3333333333303. - const float: f64 = 5.99999999999994648725e-01; - const float_ptr = &float; - const int_ptr = @ptrCast(*const i32, float_ptr); - const int_val = int_ptr.*; - if (native_endian == .Little) - try expect(int_val == 0x33333303) - else - try expect(int_val == 0x3fe33333); -} - -test "@floatToInt" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO - - try testFloatToInts(); - comptime try testFloatToInts(); -} - -fn testFloatToInts() !void { - try expectFloatToInt(f16, 255.1, u8, 255); - try expectFloatToInt(f16, 127.2, i8, 127); - try expectFloatToInt(f16, -128.2, i8, -128); -} - -fn expectFloatToInt(comptime F: type, f: F, comptime I: type, i: I) !void { - try expect(@floatToInt(I, f) == i); -} - -test "implicit cast from [*]T to ?*anyopaque" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO - - var a = [_]u8{ 3, 2, 1 }; - var runtime_zero: usize = 0; - incrementVoidPtrArray(a[runtime_zero..].ptr, 3); - try expect(std.mem.eql(u8, &a, &[_]u8{ 4, 3, 2 })); -} - -fn incrementVoidPtrArray(array: ?*anyopaque, len: usize) void { - var n: usize = 0; - while (n < len) : (n += 1) { - @ptrCast([*]u8, array.?)[n] += 1; - } -} - -test "compile time int to ptr of function" { - if (builtin.zig_backend == .stage1) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .aarch64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO - - try foobar(FUNCTION_CONSTANT); -} - -pub const FUNCTION_CONSTANT = @intToPtr(PFN_void, maxInt(usize)); -pub const PFN_void = *const fn (*anyopaque) callconv(.C) void; - -fn foobar(func: PFN_void) !void { - try std.testing.expect(@ptrToInt(func) == maxInt(usize)); -} - -test "implicit ptr to *anyopaque" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO - - var a: u32 = 1; - var ptr: *align(@alignOf(u32)) anyopaque = &a; - var b: *u32 = @ptrCast(*u32, ptr); - try expect(b.* == 1); - var ptr2: ?*align(@alignOf(u32)) anyopaque = &a; - var c: *u32 = @ptrCast(*u32, ptr2.?); - try expect(c.* == 1); -} - -const A = struct { - a: i32, -}; -test "return null from fn() anyerror!?&T" { - const a = returnNullFromOptionalTypeErrorRef(); - const b = returnNullLitFromOptionalTypeErrorRef(); - try expect((try a) == null and (try b) == null); -} -fn returnNullFromOptionalTypeErrorRef() anyerror!?*A { - const a: ?*A = null; - return a; -} -fn returnNullLitFromOptionalTypeErrorRef() anyerror!?*A { - return null; -} - -test "peer type resolution: [0]u8 and []const u8" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO - try expect(peerTypeEmptyArrayAndSlice(true, "hi").len == 0); - try expect(peerTypeEmptyArrayAndSlice(false, "hi").len == 1); - comptime { - try expect(peerTypeEmptyArrayAndSlice(true, "hi").len == 0); - try expect(peerTypeEmptyArrayAndSlice(false, "hi").len == 1); - } -} -fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 { - if (a) { - return &[_]u8{}; - } - - return slice[0..1]; -} - -test "implicitly cast from [N]T to ?[]const T" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO - try expect(mem.eql(u8, castToOptionalSlice().?, "hi")); - comptime try expect(mem.eql(u8, castToOptionalSlice().?, "hi")); -} - -fn castToOptionalSlice() ?[]const u8 { - return "hi"; -} - -test "cast u128 to f128 and back" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO - comptime try testCast128(); - try testCast128(); -} - -fn testCast128() !void { - try expect(cast128Int(cast128Float(0x7fff0000000000000000000000000000)) == 0x7fff0000000000000000000000000000); -} - -fn cast128Int(x: f128) u128 { - return @bitCast(u128, x); -} - -fn cast128Float(x: u128) f128 { - return @bitCast(f128, x); -} - -test "implicit cast from *[N]T to ?[*]T" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO - var x: ?[*]u16 = null; - var y: [4]u16 = [4]u16{ 0, 1, 2, 3 }; - - x = &y; - try expect(std.mem.eql(u16, x.?[0..4], y[0..4])); - x.?[0] = 8; - y[3] = 6; - try expect(std.mem.eql(u16, x.?[0..4], y[0..4])); -} - -test "implicit cast from *T to ?*anyopaque" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO - var a: u8 = 1; - incrementVoidPtrValue(&a); - try std.testing.expect(a == 2); -} - -fn incrementVoidPtrValue(value: ?*anyopaque) void { - @ptrCast(*u8, value.?).* += 1; -} - -test "implicit cast *[0]T to E![]const u8" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO - var x = @as(anyerror![]const u8, &[0]u8{}); - try expect((x catch unreachable).len == 0); -} - -var global_array: [4]u8 = undefined; -test "cast from array reference to fn: comptime fn ptr" { - const f = @ptrCast(*const fn () callconv(.C) void, &global_array); - try expect(@ptrToInt(f) == @ptrToInt(&global_array)); -} -test "cast from array reference to fn: runtime fn ptr" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO - var f = @ptrCast(*const fn () callconv(.C) void, &global_array); - try expect(@ptrToInt(f) == @ptrToInt(&global_array)); -} - -test "*const [N]null u8 to ?[]const u8" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO - const S = struct { - fn doTheTest() !void { - var a = "Hello"; - var b: ?[]const u8 = a; - try expect(mem.eql(u8, b.?, "Hello")); - } - }; - try S.doTheTest(); - comptime try S.doTheTest(); -} - -test "cast between [*c]T and ?[*:0]T on fn parameter" { - const S = struct { - const Handler = ?fn ([*c]const u8) callconv(.C) void; - fn addCallback(handler: Handler) void { - _ = handler; - } - - fn myCallback(cstr: ?[*:0]const u8) callconv(.C) void { - _ = cstr; - } - - fn doTheTest() void { - addCallback(myCallback); - } - }; - S.doTheTest(); -} - -var global_struct: struct { f0: usize } = undefined; -test "assignment to optional pointer result loc" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO - var foo: struct { ptr: ?*anyopaque } = .{ .ptr = &global_struct }; - try expect(foo.ptr.? == @ptrCast(*anyopaque, &global_struct)); -} - -test "cast between *[N]void and []void" { - var a: [4]void = undefined; - var b: []void = &a; - try expect(b.len == 4); -} - -test "peer resolve arrays of different size to const slice" { - try expect(mem.eql(u8, boolToStr(true), "true")); - try expect(mem.eql(u8, boolToStr(false), "false")); - comptime try expect(mem.eql(u8, boolToStr(true), "true")); - comptime try expect(mem.eql(u8, boolToStr(false), "false")); -} -fn boolToStr(b: bool) []const u8 { - return if (b) "true" else "false"; -} - -test "cast f16 to wider types" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO - const S = struct { - fn doTheTest() !void { - var x: f16 = 1234.0; - try expect(@as(f32, 1234.0) == x); - try expect(@as(f64, 1234.0) == x); - try expect(@as(f128, 1234.0) == x); - } - }; - try S.doTheTest(); - comptime try S.doTheTest(); -} - -test "cast f128 to narrower types" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO - - const S = struct { - fn doTheTest() !void { - var x: f128 = 1234.0; - try expect(@as(f16, 1234.0) == @floatCast(f16, x)); - try expect(@as(f32, 1234.0) == @floatCast(f32, x)); - try expect(@as(f64, 1234.0) == @floatCast(f64, x)); - } - }; - try S.doTheTest(); - comptime try S.doTheTest(); -} - -test "peer type resolution: unreachable, null, slice" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO - const S = struct { - fn doTheTest(num: usize, word: []const u8) !void { - const result = switch (num) { - 0 => null, - 1 => word, - else => unreachable, - }; - try expect(mem.eql(u8, result.?, "hi")); - } - }; - try S.doTheTest(1, "hi"); -} - -test "cast i8 fn call peers to i32 result" { - const S = struct { - fn doTheTest() !void { - var cond = true; - const value: i32 = if (cond) smallBoi() else bigBoi(); - try expect(value == 123); - } - fn smallBoi() i8 { - return 123; - } - fn bigBoi() i16 { - return 1234; - } - }; - try S.doTheTest(); - comptime try S.doTheTest(); -} diff --git a/test/behavior/error.zig b/test/behavior/error.zig index d58ad6ccb5..2e243d1d23 100644 --- a/test/behavior/error.zig +++ b/test/behavior/error.zig @@ -478,3 +478,29 @@ test "error union comptime caching" { S.quux(@as(anyerror!void, {})); S.quux(@as(anyerror!void, {})); } + +test "@errorName" { + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO + + try expect(mem.eql(u8, @errorName(error.AnError), "AnError")); + try expect(mem.eql(u8, @errorName(error.ALongerErrorName), "ALongerErrorName")); + try expect(mem.eql(u8, @errorName(gimmeItBroke()), "ItBroke")); +} +fn gimmeItBroke() anyerror { + return error.ItBroke; +} + +test "@errorName sentinel length matches slice length" { + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO + + const name = testBuiltinErrorName(error.FooBar); + const length: usize = 6; + try expect(length == std.mem.indexOfSentinel(u8, 0, name.ptr)); + try expect(length == name.len); +} + +pub fn testBuiltinErrorName(err: anyerror) [:0]const u8 { + return @errorName(err); +} diff --git a/test/behavior/error_llvm.zig b/test/behavior/error_llvm.zig deleted file mode 100644 index edebd5f629..0000000000 --- a/test/behavior/error_llvm.zig +++ /dev/null @@ -1,24 +0,0 @@ -const std = @import("std"); -const expect = std.testing.expect; -const mem = std.mem; - -fn gimmeItBroke() anyerror { - return error.ItBroke; -} - -test "@errorName" { - try expect(mem.eql(u8, @errorName(error.AnError), "AnError")); - try expect(mem.eql(u8, @errorName(error.ALongerErrorName), "ALongerErrorName")); - try expect(mem.eql(u8, @errorName(gimmeItBroke()), "ItBroke")); -} - -test "@errorName sentinel length matches slice length" { - const name = testBuiltinErrorName(error.FooBar); - const length: usize = 6; - try expect(length == std.mem.indexOfSentinel(u8, 0, name.ptr)); - try expect(length == name.len); -} - -pub fn testBuiltinErrorName(err: anyerror) [:0]const u8 { - return @errorName(err); -} diff --git a/test/behavior/sizeof_and_typeof.zig b/test/behavior/sizeof_and_typeof.zig index 2dbd4b3495..f359fe458e 100644 --- a/test/behavior/sizeof_and_typeof.zig +++ b/test/behavior/sizeof_and_typeof.zig @@ -1,3 +1,4 @@ +const builtin = @import("builtin"); const std = @import("std"); const expect = std.testing.expect; const expectEqual = std.testing.expectEqual; @@ -160,3 +161,115 @@ test "@bitOffsetOf" { try expect(@offsetOf(A, "f") * 8 == @bitOffsetOf(A, "f")); try expect(@offsetOf(A, "g") * 8 == @bitOffsetOf(A, "g")); } + +test "@sizeOf(T) == 0 doesn't force resolving struct size" { + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + + const S = struct { + const Foo = struct { + y: if (@sizeOf(Foo) == 0) u64 else u32, + }; + const Bar = struct { + x: i32, + y: if (0 == @sizeOf(Bar)) u64 else u32, + }; + }; + + try expect(@sizeOf(S.Foo) == 4); + try expect(@sizeOf(S.Bar) == 8); +} + +test "@TypeOf() has no runtime side effects" { + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + + const S = struct { + fn foo(comptime T: type, ptr: *T) T { + ptr.* += 1; + return ptr.*; + } + }; + var data: i32 = 0; + const T = @TypeOf(S.foo(i32, &data)); + comptime try expect(T == i32); + try expect(data == 0); +} + +test "branching logic inside @TypeOf" { + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + + const S = struct { + var data: i32 = 0; + fn foo() anyerror!i32 { + data += 1; + return undefined; + } + }; + const T = @TypeOf(S.foo() catch undefined); + comptime try expect(T == i32); + try expect(S.data == 0); +} + +test "@bitSizeOf" { + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + + try expect(@bitSizeOf(u2) == 2); + try expect(@bitSizeOf(u8) == @sizeOf(u8) * 8); + try expect(@bitSizeOf(struct { + a: u2, + }) == 8); + try expect(@bitSizeOf(packed struct { + a: u2, + }) == 2); +} + +test "@sizeOf comparison against zero" { + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + + const S0 = struct { + f: *@This(), + }; + const U0 = union { + f: *@This(), + }; + const S1 = struct { + fn H(comptime T: type) type { + return struct { + x: T, + }; + } + f0: H(*@This()), + f1: H(**@This()), + f2: H(***@This()), + }; + const U1 = union { + fn H(comptime T: type) type { + return struct { + x: T, + }; + } + f0: H(*@This()), + f1: H(**@This()), + f2: H(***@This()), + }; + const S = struct { + fn doTheTest(comptime T: type, comptime result: bool) !void { + try expectEqual(result, @sizeOf(T) > 0); + } + }; + // Zero-sized type + try S.doTheTest(u0, false); + try S.doTheTest(*u0, false); + // Non byte-sized type + try S.doTheTest(u1, true); + try S.doTheTest(*u1, true); + // Regular type + try S.doTheTest(u8, true); + try S.doTheTest(*u8, true); + try S.doTheTest(f32, true); + try S.doTheTest(*f32, true); + // Container with ptr pointing to themselves + try S.doTheTest(S0, true); + try S.doTheTest(U0, true); + try S.doTheTest(S1, true); + try S.doTheTest(U1, true); +} diff --git a/test/behavior/sizeof_and_typeof_stage1.zig b/test/behavior/sizeof_and_typeof_stage1.zig deleted file mode 100644 index 20cefef0e7..0000000000 --- a/test/behavior/sizeof_and_typeof_stage1.zig +++ /dev/null @@ -1,105 +0,0 @@ -const std = @import("std"); -const expect = std.testing.expect; -const expectEqual = std.testing.expectEqual; - -test "@sizeOf(T) == 0 doesn't force resolving struct size" { - const S = struct { - const Foo = struct { - y: if (@sizeOf(Foo) == 0) u64 else u32, - }; - const Bar = struct { - x: i32, - y: if (0 == @sizeOf(Bar)) u64 else u32, - }; - }; - - try expect(@sizeOf(S.Foo) == 4); - try expect(@sizeOf(S.Bar) == 8); -} - -test "@TypeOf() has no runtime side effects" { - const S = struct { - fn foo(comptime T: type, ptr: *T) T { - ptr.* += 1; - return ptr.*; - } - }; - var data: i32 = 0; - const T = @TypeOf(S.foo(i32, &data)); - comptime try expect(T == i32); - try expect(data == 0); -} - -test "branching logic inside @TypeOf" { - const S = struct { - var data: i32 = 0; - fn foo() anyerror!i32 { - data += 1; - return undefined; - } - }; - const T = @TypeOf(S.foo() catch undefined); - comptime try expect(T == i32); - try expect(S.data == 0); -} - -test "@bitSizeOf" { - try expect(@bitSizeOf(u2) == 2); - try expect(@bitSizeOf(u8) == @sizeOf(u8) * 8); - try expect(@bitSizeOf(struct { - a: u2, - }) == 8); - try expect(@bitSizeOf(packed struct { - a: u2, - }) == 2); -} - -test "@sizeOf comparison against zero" { - const S0 = struct { - f: *@This(), - }; - const U0 = union { - f: *@This(), - }; - const S1 = struct { - fn H(comptime T: type) type { - return struct { - x: T, - }; - } - f0: H(*@This()), - f1: H(**@This()), - f2: H(***@This()), - }; - const U1 = union { - fn H(comptime T: type) type { - return struct { - x: T, - }; - } - f0: H(*@This()), - f1: H(**@This()), - f2: H(***@This()), - }; - const S = struct { - fn doTheTest(comptime T: type, comptime result: bool) !void { - try expectEqual(result, @sizeOf(T) > 0); - } - }; - // Zero-sized type - try S.doTheTest(u0, false); - try S.doTheTest(*u0, false); - // Non byte-sized type - try S.doTheTest(u1, true); - try S.doTheTest(*u1, true); - // Regular type - try S.doTheTest(u8, true); - try S.doTheTest(*u8, true); - try S.doTheTest(f32, true); - try S.doTheTest(*f32, true); - // Container with ptr pointing to themselves - try S.doTheTest(S0, true); - try S.doTheTest(U0, true); - try S.doTheTest(S1, true); - try S.doTheTest(U1, true); -} diff --git a/test/behavior/struct.zig b/test/behavior/struct.zig index 03be28b9d1..ecdd6a1846 100644 --- a/test/behavior/struct.zig +++ b/test/behavior/struct.zig @@ -133,15 +133,6 @@ fn returnEmptyStructInstance() StructWithNoFields { return empty_global_instance; } -const Node = struct { - val: Val, - next: *Node, -}; - -const Val = struct { - x: i32, -}; - test "fn call of struct field" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; @@ -294,3 +285,888 @@ const blah: packed struct { test "bit field alignment" { try expect(@TypeOf(&blah.b) == *align(1:3:1) const u3); } + +const Node = struct { + val: Val, + next: *Node, +}; + +const Val = struct { + x: i32, +}; + +test "struct point to self" { + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + + var root: Node = undefined; + root.val.x = 1; + + var node: Node = undefined; + node.next = &root; + node.val.x = 2; + + root.next = &node; + + try expect(node.next.next.next.val.x == 1); +} + +test "void struct fields" { + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + + const foo = VoidStructFieldsFoo{ + .a = void{}, + .b = 1, + .c = void{}, + }; + try expect(foo.b == 1); + try expect(@sizeOf(VoidStructFieldsFoo) == 4); +} +const VoidStructFieldsFoo = struct { + a: void, + b: i32, + c: void, +}; + +test "return empty struct from fn" { + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + + _ = testReturnEmptyStructFromFn(); +} +const EmptyStruct2 = struct {}; +fn testReturnEmptyStructFromFn() EmptyStruct2 { + return EmptyStruct2{}; +} + +test "pass slice of empty struct to fn" { + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + + try expect(testPassSliceOfEmptyStructToFn(&[_]EmptyStruct2{EmptyStruct2{}}) == 1); +} +fn testPassSliceOfEmptyStructToFn(slice: []const EmptyStruct2) usize { + return slice.len; +} + +test "self-referencing struct via array member" { + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + + const T = struct { + children: [1]*@This(), + }; + var x: T = undefined; + x = T{ .children = .{&x} }; + try expect(x.children[0] == &x); +} + +test "empty struct method call" { + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + + const es = EmptyStruct{}; + try expect(es.method() == 1234); +} +const EmptyStruct = struct { + fn method(es: *const EmptyStruct) i32 { + _ = es; + return 1234; + } +}; + +test "align 1 field before self referential align 8 field as slice return type" { + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + + const result = alloc(Expr); + try expect(result.len == 0); +} + +const Expr = union(enum) { + Literal: u8, + Question: *Expr, +}; + +fn alloc(comptime T: type) []T { + return &[_]T{}; +} + +const APackedStruct = packed struct { + x: u8, + y: u8, +}; + +test "packed struct" { + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + + var foo = APackedStruct{ + .x = 1, + .y = 2, + }; + foo.y += 1; + const four = foo.x + foo.y; + try expect(four == 4); +} + +const Foo24Bits = packed struct { + field: u24, +}; +const Foo96Bits = packed struct { + a: u24, + b: u24, + c: u24, + d: u24, +}; + +test "packed struct 24bits" { + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + + comptime { + try expect(@sizeOf(Foo24Bits) == 4); + if (@sizeOf(usize) == 4) { + try expect(@sizeOf(Foo96Bits) == 12); + } else { + try expect(@sizeOf(Foo96Bits) == 16); + } + } + + var value = Foo96Bits{ + .a = 0, + .b = 0, + .c = 0, + .d = 0, + }; + value.a += 1; + try expect(value.a == 1); + try expect(value.b == 0); + try expect(value.c == 0); + try expect(value.d == 0); + + value.b += 1; + try expect(value.a == 1); + try expect(value.b == 1); + try expect(value.c == 0); + try expect(value.d == 0); + + value.c += 1; + try expect(value.a == 1); + try expect(value.b == 1); + try expect(value.c == 1); + try expect(value.d == 0); + + value.d += 1; + try expect(value.a == 1); + try expect(value.b == 1); + try expect(value.c == 1); + try expect(value.d == 1); +} + +test "runtime struct initialization of bitfield" { + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + + const s1 = Nibbles{ + .x = x1, + .y = x1, + }; + const s2 = Nibbles{ + .x = @intCast(u4, x2), + .y = @intCast(u4, x2), + }; + + try expect(s1.x == x1); + try expect(s1.y == x1); + try expect(s2.x == @intCast(u4, x2)); + try expect(s2.y == @intCast(u4, x2)); +} + +var x1 = @as(u4, 1); +var x2 = @as(u8, 2); + +const Nibbles = packed struct { + x: u4, + y: u4, +}; + +const Bitfields = packed struct { + f1: u16, + f2: u16, + f3: u8, + f4: u8, + f5: u4, + f6: u4, + f7: u8, +}; + +test "native bit field understands endianness" { + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + + var all: u64 = if (native_endian != .Little) + 0x1111222233445677 + else + 0x7765443322221111; + var bytes: [8]u8 = undefined; + @memcpy(&bytes, @ptrCast([*]u8, &all), 8); + var bitfields = @ptrCast(*Bitfields, &bytes).*; + + try expect(bitfields.f1 == 0x1111); + try expect(bitfields.f2 == 0x2222); + try expect(bitfields.f3 == 0x33); + try expect(bitfields.f4 == 0x44); + try expect(bitfields.f5 == 0x5); + try expect(bitfields.f6 == 0x6); + try expect(bitfields.f7 == 0x77); +} + +test "implicit cast packed struct field to const ptr" { + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + + const LevelUpMove = packed struct { + move_id: u9, + level: u7, + + fn toInt(value: u7) u7 { + return value; + } + }; + + var lup: LevelUpMove = undefined; + lup.level = 12; + const res = LevelUpMove.toInt(lup.level); + try expect(res == 12); +} + +test "zero-bit field in packed struct" { + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + + const S = packed struct { + x: u10, + y: void, + }; + var x: S = undefined; + _ = x; +} + +test "packed struct with non-ABI-aligned field" { + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + + const S = packed struct { + x: u9, + y: u183, + }; + var s: S = undefined; + s.x = 1; + s.y = 42; + try expect(s.x == 1); + try expect(s.y == 42); +} + +const BitField1 = packed struct { + a: u3, + b: u3, + c: u2, +}; + +const bit_field_1 = BitField1{ + .a = 1, + .b = 2, + .c = 3, +}; + +test "bit field access" { + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + + var data = bit_field_1; + try expect(getA(&data) == 1); + try expect(getB(&data) == 2); + try expect(getC(&data) == 3); + comptime try expect(@sizeOf(BitField1) == 1); + + data.b += 1; + try expect(data.b == 3); + + data.a += 1; + try expect(data.a == 2); + try expect(data.b == 3); +} + +fn getA(data: *const BitField1) u3 { + return data.a; +} + +fn getB(data: *const BitField1) u3 { + return data.b; +} + +fn getC(data: *const BitField1) u2 { + return data.c; +} + +test "default struct initialization fields" { + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + + const S = struct { + a: i32 = 1234, + b: i32, + }; + const x = S{ + .b = 5, + }; + var five: i32 = 5; + const y = S{ + .b = five, + }; + if (x.a + x.b != 1239) { + @compileError("it should be comptime known"); + } + try expect(y.a == x.a); + try expect(y.b == x.b); + try expect(1239 == x.a + x.b); +} + +// TODO revisit this test when doing https://github.com/ziglang/zig/issues/1512 +test "packed array 24bits" { + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + + comptime { + try expect(@sizeOf([9]Foo32Bits) == 9 * 4); + try expect(@sizeOf(FooArray24Bits) == 2 + 2 * 4 + 2); + } + + var bytes = [_]u8{0} ** (@sizeOf(FooArray24Bits) + 1); + bytes[bytes.len - 1] = 0xaa; + const ptr = &std.mem.bytesAsSlice(FooArray24Bits, bytes[0 .. bytes.len - 1])[0]; + try expect(ptr.a == 0); + try expect(ptr.b[0].field == 0); + try expect(ptr.b[1].field == 0); + try expect(ptr.c == 0); + + ptr.a = maxInt(u16); + try expect(ptr.a == maxInt(u16)); + try expect(ptr.b[0].field == 0); + try expect(ptr.b[1].field == 0); + try expect(ptr.c == 0); + + ptr.b[0].field = maxInt(u24); + try expect(ptr.a == maxInt(u16)); + try expect(ptr.b[0].field == maxInt(u24)); + try expect(ptr.b[1].field == 0); + try expect(ptr.c == 0); + + ptr.b[1].field = maxInt(u24); + try expect(ptr.a == maxInt(u16)); + try expect(ptr.b[0].field == maxInt(u24)); + try expect(ptr.b[1].field == maxInt(u24)); + try expect(ptr.c == 0); + + ptr.c = maxInt(u16); + try expect(ptr.a == maxInt(u16)); + try expect(ptr.b[0].field == maxInt(u24)); + try expect(ptr.b[1].field == maxInt(u24)); + try expect(ptr.c == maxInt(u16)); + + try expect(bytes[bytes.len - 1] == 0xaa); +} + +const Foo32Bits = packed struct { + field: u24, + pad: u8, +}; + +const FooArray24Bits = packed struct { + a: u16, + b: [2]Foo32Bits, + c: u16, +}; + +test "aligned array of packed struct" { + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + + comptime { + try expect(@sizeOf(FooStructAligned) == 2); + try expect(@sizeOf(FooArrayOfAligned) == 2 * 2); + } + + var bytes = [_]u8{0xbb} ** @sizeOf(FooArrayOfAligned); + const ptr = &std.mem.bytesAsSlice(FooArrayOfAligned, bytes[0..])[0]; + + try expect(ptr.a[0].a == 0xbb); + try expect(ptr.a[0].b == 0xbb); + try expect(ptr.a[1].a == 0xbb); + try expect(ptr.a[1].b == 0xbb); +} + +const FooStructAligned = packed struct { + a: u8, + b: u8, +}; + +const FooArrayOfAligned = packed struct { + a: [2]FooStructAligned, +}; + +test "pointer to packed struct member in a stack variable" { + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + + const S = packed struct { + a: u2, + b: u2, + }; + + var s = S{ .a = 2, .b = 0 }; + var b_ptr = &s.b; + try expect(s.b == 0); + b_ptr.* = 2; + try expect(s.b == 2); +} + +test "non-byte-aligned array inside packed struct" { + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + + const Foo = packed struct { + a: bool, + b: [0x16]u8, + }; + const S = struct { + fn bar(slice: []const u8) !void { + try expectEqualSlices(u8, slice, "abcdefghijklmnopqurstu"); + } + fn doTheTest() !void { + var foo = Foo{ + .a = true, + .b = "abcdefghijklmnopqurstu".*, + }; + const value = foo.b; + try bar(&value); + } + }; + try S.doTheTest(); + comptime try S.doTheTest(); +} + +test "packed struct with u0 field access" { + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + + const S = packed struct { + f0: u0, + }; + var s = S{ .f0 = 0 }; + comptime try expect(s.f0 == 0); +} + +test "access to global struct fields" { + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + + g_foo.bar.value = 42; + try expect(g_foo.bar.value == 42); +} + +const S0 = struct { + bar: S1, + + pub const S1 = struct { + value: u8, + }; + + fn init() @This() { + return S0{ .bar = S1{ .value = 123 } }; + } +}; + +var g_foo: S0 = S0.init(); + +test "packed struct with fp fields" { + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + + const S = packed struct { + data: [3]f32, + + pub fn frob(self: *@This()) void { + self.data[0] += self.data[1] + self.data[2]; + self.data[1] += self.data[0] + self.data[2]; + self.data[2] += self.data[0] + self.data[1]; + } + }; + + var s: S = undefined; + s.data[0] = 1.0; + s.data[1] = 2.0; + s.data[2] = 3.0; + s.frob(); + try expectEqual(@as(f32, 6.0), s.data[0]); + try expectEqual(@as(f32, 11.0), s.data[1]); + try expectEqual(@as(f32, 20.0), s.data[2]); +} + +test "fn with C calling convention returns struct by value" { + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + + const S = struct { + fn entry() !void { + var x = makeBar(10); + try expectEqual(@as(i32, 10), x.handle); + } + + const ExternBar = extern struct { + handle: i32, + }; + + fn makeBar(t: i32) callconv(.C) ExternBar { + return ExternBar{ + .handle = t, + }; + } + }; + try S.entry(); + comptime try S.entry(); +} + +test "non-packed struct with u128 entry in union" { + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + + const U = union(enum) { + Num: u128, + Void, + }; + + const S = struct { + f1: U, + f2: U, + }; + + var sx: S = undefined; + var s = &sx; + try std.testing.expect(@ptrToInt(&s.f2) - @ptrToInt(&s.f1) == @offsetOf(S, "f2")); + var v2 = U{ .Num = 123 }; + s.f2 = v2; + try std.testing.expect(s.f2.Num == 123); +} + +test "packed struct field passed to generic function" { + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + + const S = struct { + const P = packed struct { + b: u5, + g: u5, + r: u5, + a: u1, + }; + + fn genericReadPackedField(ptr: anytype) u5 { + return ptr.*; + } + }; + + var p: S.P = undefined; + p.b = 29; + var loaded = S.genericReadPackedField(&p.b); + try expect(loaded == 29); +} + +test "anonymous struct literal syntax" { + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + + const S = struct { + const Point = struct { + x: i32, + y: i32, + }; + + fn doTheTest() !void { + var p: Point = .{ + .x = 1, + .y = 2, + }; + try expect(p.x == 1); + try expect(p.y == 2); + } + }; + try S.doTheTest(); + comptime try S.doTheTest(); +} + +test "fully anonymous struct" { + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + + const S = struct { + fn doTheTest() !void { + try dump(.{ + .int = @as(u32, 1234), + .float = @as(f64, 12.34), + .b = true, + .s = "hi", + }); + } + fn dump(args: anytype) !void { + try expect(args.int == 1234); + try expect(args.float == 12.34); + try expect(args.b); + try expect(args.s[0] == 'h'); + try expect(args.s[1] == 'i'); + } + }; + try S.doTheTest(); + comptime try S.doTheTest(); +} + +test "fully anonymous list literal" { + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + + const S = struct { + fn doTheTest() !void { + try dump(.{ @as(u32, 1234), @as(f64, 12.34), true, "hi" }); + } + fn dump(args: anytype) !void { + try expect(args.@"0" == 1234); + try expect(args.@"1" == 12.34); + try expect(args.@"2"); + try expect(args.@"3"[0] == 'h'); + try expect(args.@"3"[1] == 'i'); + } + }; + try S.doTheTest(); + comptime try S.doTheTest(); +} + +test "anonymous struct literal assigned to variable" { + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + + var vec = .{ @as(i32, 22), @as(i32, 55), @as(i32, 99) }; + try expect(vec.@"0" == 22); + try expect(vec.@"1" == 55); + try expect(vec.@"2" == 99); +} + +test "comptime struct field" { + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + + const T = struct { + a: i32, + comptime b: i32 = 1234, + }; + + var foo: T = undefined; + comptime try expect(foo.b == 1234); +} + +test "anon struct literal field value initialized with fn call" { + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + + const S = struct { + fn doTheTest() !void { + var x = .{foo()}; + try expectEqualSlices(u8, x[0], "hi"); + } + fn foo() []const u8 { + return "hi"; + } + }; + try S.doTheTest(); + comptime try S.doTheTest(); +} + +test "struct with union field" { + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + + const Value = struct { + ref: u32 = 2, + kind: union(enum) { + None: usize, + Bool: bool, + }, + }; + + var True = Value{ + .kind = .{ .Bool = true }, + }; + try expectEqual(@as(u32, 2), True.ref); + try expectEqual(true, True.kind.Bool); +} + +test "type coercion of anon struct literal to struct" { + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + + const S = struct { + const S2 = struct { + A: u32, + B: []const u8, + C: void, + D: Foo = .{}, + }; + + const Foo = struct { + field: i32 = 1234, + }; + + fn doTheTest() !void { + var y: u32 = 42; + const t0 = .{ .A = 123, .B = "foo", .C = {} }; + const t1 = .{ .A = y, .B = "foo", .C = {} }; + const y0: S2 = t0; + var y1: S2 = t1; + try expect(y0.A == 123); + try expect(std.mem.eql(u8, y0.B, "foo")); + try expect(y0.C == {}); + try expect(y0.D.field == 1234); + try expect(y1.A == y); + try expect(std.mem.eql(u8, y1.B, "foo")); + try expect(y1.C == {}); + try expect(y1.D.field == 1234); + } + }; + try S.doTheTest(); + comptime try S.doTheTest(); +} + +test "type coercion of pointer to anon struct literal to pointer to struct" { + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + + const S = struct { + const S2 = struct { + A: u32, + B: []const u8, + C: void, + D: Foo = .{}, + }; + + const Foo = struct { + field: i32 = 1234, + }; + + fn doTheTest() !void { + var y: u32 = 42; + const t0 = &.{ .A = 123, .B = "foo", .C = {} }; + const t1 = &.{ .A = y, .B = "foo", .C = {} }; + const y0: *const S2 = t0; + var y1: *const S2 = t1; + try expect(y0.A == 123); + try expect(std.mem.eql(u8, y0.B, "foo")); + try expect(y0.C == {}); + try expect(y0.D.field == 1234); + try expect(y1.A == y); + try expect(std.mem.eql(u8, y1.B, "foo")); + try expect(y1.C == {}); + try expect(y1.D.field == 1234); + } + }; + try S.doTheTest(); + comptime try S.doTheTest(); +} + +test "packed struct with undefined initializers" { + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + + const S = struct { + const P = packed struct { + a: u3, + _a: u3 = undefined, + b: u3, + _b: u3 = undefined, + c: u3, + _c: u3 = undefined, + }; + + fn doTheTest() !void { + var p: P = undefined; + p = P{ .a = 2, .b = 4, .c = 6 }; + // Make sure the compiler doesn't touch the unprefixed fields. + // Use expect since i386-linux doesn't like expectEqual + try expect(p.a == 2); + try expect(p.b == 4); + try expect(p.c == 6); + } + }; + + try S.doTheTest(); + comptime try S.doTheTest(); +} + +test "for loop over pointers to struct, getting field from struct pointer" { + // When enabling this test, be careful. I have observed it to pass when compiling + // stage2 alone, but when using stage1 with -fno-stage1 -fLLVM it fails. + // Maybe eyeball the LLVM that it generates and run in valgrind, both the compiler + // and the generated test at runtime. + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + + const S = struct { + const Foo = struct { + name: []const u8, + }; + + var ok = true; + + fn eql(a: []const u8) bool { + _ = a; + return true; + } + + const ArrayList = struct { + fn toSlice(self: *ArrayList) []*Foo { + _ = self; + return @as([*]*Foo, undefined)[0..0]; + } + }; + + fn doTheTest() !void { + var objects: ArrayList = undefined; + + for (objects.toSlice()) |obj| { + if (eql(obj.name)) { + ok = false; + } + } + + try expect(ok); + } + }; + try S.doTheTest(); +} diff --git a/test/behavior/struct_llvm.zig b/test/behavior/struct_llvm.zig deleted file mode 100644 index eef7b16487..0000000000 --- a/test/behavior/struct_llvm.zig +++ /dev/null @@ -1,802 +0,0 @@ -const std = @import("std"); -const builtin = @import("builtin"); -const native_endian = builtin.target.cpu.arch.endian(); -const expect = std.testing.expect; -const expectEqual = std.testing.expectEqual; -const expectEqualSlices = std.testing.expectEqualSlices; -const maxInt = std.math.maxInt; - -const Node = struct { - val: Val, - next: *Node, -}; - -const Val = struct { - x: i32, -}; - -test "struct point to self" { - var root: Node = undefined; - root.val.x = 1; - - var node: Node = undefined; - node.next = &root; - node.val.x = 2; - - root.next = &node; - - try expect(node.next.next.next.val.x == 1); -} - -test "void struct fields" { - const foo = VoidStructFieldsFoo{ - .a = void{}, - .b = 1, - .c = void{}, - }; - try expect(foo.b == 1); - try expect(@sizeOf(VoidStructFieldsFoo) == 4); -} -const VoidStructFieldsFoo = struct { - a: void, - b: i32, - c: void, -}; - -test "return empty struct from fn" { - _ = testReturnEmptyStructFromFn(); -} -const EmptyStruct2 = struct {}; -fn testReturnEmptyStructFromFn() EmptyStruct2 { - return EmptyStruct2{}; -} - -test "pass slice of empty struct to fn" { - try expect(testPassSliceOfEmptyStructToFn(&[_]EmptyStruct2{EmptyStruct2{}}) == 1); -} -fn testPassSliceOfEmptyStructToFn(slice: []const EmptyStruct2) usize { - return slice.len; -} - -test "self-referencing struct via array member" { - const T = struct { - children: [1]*@This(), - }; - var x: T = undefined; - x = T{ .children = .{&x} }; - try expect(x.children[0] == &x); -} - -test "empty struct method call" { - const es = EmptyStruct{}; - try expect(es.method() == 1234); -} -const EmptyStruct = struct { - fn method(es: *const EmptyStruct) i32 { - _ = es; - return 1234; - } -}; - -test "align 1 field before self referential align 8 field as slice return type" { - const result = alloc(Expr); - try expect(result.len == 0); -} - -const Expr = union(enum) { - Literal: u8, - Question: *Expr, -}; - -fn alloc(comptime T: type) []T { - return &[_]T{}; -} - -const APackedStruct = packed struct { - x: u8, - y: u8, -}; - -test "packed struct" { - var foo = APackedStruct{ - .x = 1, - .y = 2, - }; - foo.y += 1; - const four = foo.x + foo.y; - try expect(four == 4); -} - -const Foo24Bits = packed struct { - field: u24, -}; -const Foo96Bits = packed struct { - a: u24, - b: u24, - c: u24, - d: u24, -}; - -test "packed struct 24bits" { - comptime { - try expect(@sizeOf(Foo24Bits) == 4); - if (@sizeOf(usize) == 4) { - try expect(@sizeOf(Foo96Bits) == 12); - } else { - try expect(@sizeOf(Foo96Bits) == 16); - } - } - - var value = Foo96Bits{ - .a = 0, - .b = 0, - .c = 0, - .d = 0, - }; - value.a += 1; - try expect(value.a == 1); - try expect(value.b == 0); - try expect(value.c == 0); - try expect(value.d == 0); - - value.b += 1; - try expect(value.a == 1); - try expect(value.b == 1); - try expect(value.c == 0); - try expect(value.d == 0); - - value.c += 1; - try expect(value.a == 1); - try expect(value.b == 1); - try expect(value.c == 1); - try expect(value.d == 0); - - value.d += 1; - try expect(value.a == 1); - try expect(value.b == 1); - try expect(value.c == 1); - try expect(value.d == 1); -} - -test "runtime struct initialization of bitfield" { - const s1 = Nibbles{ - .x = x1, - .y = x1, - }; - const s2 = Nibbles{ - .x = @intCast(u4, x2), - .y = @intCast(u4, x2), - }; - - try expect(s1.x == x1); - try expect(s1.y == x1); - try expect(s2.x == @intCast(u4, x2)); - try expect(s2.y == @intCast(u4, x2)); -} - -var x1 = @as(u4, 1); -var x2 = @as(u8, 2); - -const Nibbles = packed struct { - x: u4, - y: u4, -}; - -const Bitfields = packed struct { - f1: u16, - f2: u16, - f3: u8, - f4: u8, - f5: u4, - f6: u4, - f7: u8, -}; - -test "native bit field understands endianness" { - var all: u64 = if (native_endian != .Little) - 0x1111222233445677 - else - 0x7765443322221111; - var bytes: [8]u8 = undefined; - @memcpy(&bytes, @ptrCast([*]u8, &all), 8); - var bitfields = @ptrCast(*Bitfields, &bytes).*; - - try expect(bitfields.f1 == 0x1111); - try expect(bitfields.f2 == 0x2222); - try expect(bitfields.f3 == 0x33); - try expect(bitfields.f4 == 0x44); - try expect(bitfields.f5 == 0x5); - try expect(bitfields.f6 == 0x6); - try expect(bitfields.f7 == 0x77); -} - -test "implicit cast packed struct field to const ptr" { - const LevelUpMove = packed struct { - move_id: u9, - level: u7, - - fn toInt(value: u7) u7 { - return value; - } - }; - - var lup: LevelUpMove = undefined; - lup.level = 12; - const res = LevelUpMove.toInt(lup.level); - try expect(res == 12); -} - -test "zero-bit field in packed struct" { - const S = packed struct { - x: u10, - y: void, - }; - var x: S = undefined; - _ = x; -} - -test "packed struct with non-ABI-aligned field" { - const S = packed struct { - x: u9, - y: u183, - }; - var s: S = undefined; - s.x = 1; - s.y = 42; - try expect(s.x == 1); - try expect(s.y == 42); -} - -const BitField1 = packed struct { - a: u3, - b: u3, - c: u2, -}; - -const bit_field_1 = BitField1{ - .a = 1, - .b = 2, - .c = 3, -}; - -test "bit field access" { - var data = bit_field_1; - try expect(getA(&data) == 1); - try expect(getB(&data) == 2); - try expect(getC(&data) == 3); - comptime try expect(@sizeOf(BitField1) == 1); - - data.b += 1; - try expect(data.b == 3); - - data.a += 1; - try expect(data.a == 2); - try expect(data.b == 3); -} - -fn getA(data: *const BitField1) u3 { - return data.a; -} - -fn getB(data: *const BitField1) u3 { - return data.b; -} - -fn getC(data: *const BitField1) u2 { - return data.c; -} - -test "default struct initialization fields" { - const S = struct { - a: i32 = 1234, - b: i32, - }; - const x = S{ - .b = 5, - }; - var five: i32 = 5; - const y = S{ - .b = five, - }; - if (x.a + x.b != 1239) { - @compileError("it should be comptime known"); - } - try expect(y.a == x.a); - try expect(y.b == x.b); - try expect(1239 == x.a + x.b); -} - -// TODO revisit this test when doing https://github.com/ziglang/zig/issues/1512 -test "packed array 24bits" { - if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO - - comptime { - try expect(@sizeOf([9]Foo32Bits) == 9 * 4); - try expect(@sizeOf(FooArray24Bits) == 2 + 2 * 4 + 2); - } - - var bytes = [_]u8{0} ** (@sizeOf(FooArray24Bits) + 1); - bytes[bytes.len - 1] = 0xaa; - const ptr = &std.mem.bytesAsSlice(FooArray24Bits, bytes[0 .. bytes.len - 1])[0]; - try expect(ptr.a == 0); - try expect(ptr.b[0].field == 0); - try expect(ptr.b[1].field == 0); - try expect(ptr.c == 0); - - ptr.a = maxInt(u16); - try expect(ptr.a == maxInt(u16)); - try expect(ptr.b[0].field == 0); - try expect(ptr.b[1].field == 0); - try expect(ptr.c == 0); - - ptr.b[0].field = maxInt(u24); - try expect(ptr.a == maxInt(u16)); - try expect(ptr.b[0].field == maxInt(u24)); - try expect(ptr.b[1].field == 0); - try expect(ptr.c == 0); - - ptr.b[1].field = maxInt(u24); - try expect(ptr.a == maxInt(u16)); - try expect(ptr.b[0].field == maxInt(u24)); - try expect(ptr.b[1].field == maxInt(u24)); - try expect(ptr.c == 0); - - ptr.c = maxInt(u16); - try expect(ptr.a == maxInt(u16)); - try expect(ptr.b[0].field == maxInt(u24)); - try expect(ptr.b[1].field == maxInt(u24)); - try expect(ptr.c == maxInt(u16)); - - try expect(bytes[bytes.len - 1] == 0xaa); -} - -const Foo32Bits = packed struct { - field: u24, - pad: u8, -}; - -const FooArray24Bits = packed struct { - a: u16, - b: [2]Foo32Bits, - c: u16, -}; - -test "aligned array of packed struct" { - if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO - - comptime { - try expect(@sizeOf(FooStructAligned) == 2); - try expect(@sizeOf(FooArrayOfAligned) == 2 * 2); - } - - var bytes = [_]u8{0xbb} ** @sizeOf(FooArrayOfAligned); - const ptr = &std.mem.bytesAsSlice(FooArrayOfAligned, bytes[0..])[0]; - - try expect(ptr.a[0].a == 0xbb); - try expect(ptr.a[0].b == 0xbb); - try expect(ptr.a[1].a == 0xbb); - try expect(ptr.a[1].b == 0xbb); -} - -const FooStructAligned = packed struct { - a: u8, - b: u8, -}; - -const FooArrayOfAligned = packed struct { - a: [2]FooStructAligned, -}; - -test "pointer to packed struct member in a stack variable" { - if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO - - const S = packed struct { - a: u2, - b: u2, - }; - - var s = S{ .a = 2, .b = 0 }; - var b_ptr = &s.b; - try expect(s.b == 0); - b_ptr.* = 2; - try expect(s.b == 2); -} - -test "non-byte-aligned array inside packed struct" { - if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO - - const Foo = packed struct { - a: bool, - b: [0x16]u8, - }; - const S = struct { - fn bar(slice: []const u8) !void { - try expectEqualSlices(u8, slice, "abcdefghijklmnopqurstu"); - } - fn doTheTest() !void { - var foo = Foo{ - .a = true, - .b = "abcdefghijklmnopqurstu".*, - }; - const value = foo.b; - try bar(&value); - } - }; - try S.doTheTest(); - comptime try S.doTheTest(); -} - -test "packed struct with u0 field access" { - if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO - - const S = packed struct { - f0: u0, - }; - var s = S{ .f0 = 0 }; - comptime try expect(s.f0 == 0); -} - -test "access to global struct fields" { - if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO - - g_foo.bar.value = 42; - try expect(g_foo.bar.value == 42); -} - -const S0 = struct { - bar: S1, - - pub const S1 = struct { - value: u8, - }; - - fn init() @This() { - return S0{ .bar = S1{ .value = 123 } }; - } -}; - -var g_foo: S0 = S0.init(); - -test "packed struct with fp fields" { - if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO - - const S = packed struct { - data: [3]f32, - - pub fn frob(self: *@This()) void { - self.data[0] += self.data[1] + self.data[2]; - self.data[1] += self.data[0] + self.data[2]; - self.data[2] += self.data[0] + self.data[1]; - } - }; - - var s: S = undefined; - s.data[0] = 1.0; - s.data[1] = 2.0; - s.data[2] = 3.0; - s.frob(); - try expectEqual(@as(f32, 6.0), s.data[0]); - try expectEqual(@as(f32, 11.0), s.data[1]); - try expectEqual(@as(f32, 20.0), s.data[2]); -} - -test "fn with C calling convention returns struct by value" { - if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO - - const S = struct { - fn entry() !void { - var x = makeBar(10); - try expectEqual(@as(i32, 10), x.handle); - } - - const ExternBar = extern struct { - handle: i32, - }; - - fn makeBar(t: i32) callconv(.C) ExternBar { - return ExternBar{ - .handle = t, - }; - } - }; - try S.entry(); - comptime try S.entry(); -} - -test "non-packed struct with u128 entry in union" { - if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO - - const U = union(enum) { - Num: u128, - Void, - }; - - const S = struct { - f1: U, - f2: U, - }; - - var sx: S = undefined; - var s = &sx; - try std.testing.expect(@ptrToInt(&s.f2) - @ptrToInt(&s.f1) == @offsetOf(S, "f2")); - var v2 = U{ .Num = 123 }; - s.f2 = v2; - try std.testing.expect(s.f2.Num == 123); -} - -test "packed struct field passed to generic function" { - if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO - - const S = struct { - const P = packed struct { - b: u5, - g: u5, - r: u5, - a: u1, - }; - - fn genericReadPackedField(ptr: anytype) u5 { - return ptr.*; - } - }; - - var p: S.P = undefined; - p.b = 29; - var loaded = S.genericReadPackedField(&p.b); - try expect(loaded == 29); -} - -test "anonymous struct literal syntax" { - const S = struct { - const Point = struct { - x: i32, - y: i32, - }; - - fn doTheTest() !void { - var p: Point = .{ - .x = 1, - .y = 2, - }; - try expect(p.x == 1); - try expect(p.y == 2); - } - }; - try S.doTheTest(); - comptime try S.doTheTest(); -} - -test "fully anonymous struct" { - if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO - - const S = struct { - fn doTheTest() !void { - try dump(.{ - .int = @as(u32, 1234), - .float = @as(f64, 12.34), - .b = true, - .s = "hi", - }); - } - fn dump(args: anytype) !void { - try expect(args.int == 1234); - try expect(args.float == 12.34); - try expect(args.b); - try expect(args.s[0] == 'h'); - try expect(args.s[1] == 'i'); - } - }; - try S.doTheTest(); - comptime try S.doTheTest(); -} - -test "fully anonymous list literal" { - if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO - - const S = struct { - fn doTheTest() !void { - try dump(.{ @as(u32, 1234), @as(f64, 12.34), true, "hi" }); - } - fn dump(args: anytype) !void { - try expect(args.@"0" == 1234); - try expect(args.@"1" == 12.34); - try expect(args.@"2"); - try expect(args.@"3"[0] == 'h'); - try expect(args.@"3"[1] == 'i'); - } - }; - try S.doTheTest(); - comptime try S.doTheTest(); -} - -test "anonymous struct literal assigned to variable" { - if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO - - var vec = .{ @as(i32, 22), @as(i32, 55), @as(i32, 99) }; - try expect(vec.@"0" == 22); - try expect(vec.@"1" == 55); - try expect(vec.@"2" == 99); -} - -test "comptime struct field" { - if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO - - const T = struct { - a: i32, - comptime b: i32 = 1234, - }; - - var foo: T = undefined; - comptime try expect(foo.b == 1234); -} - -test "anon struct literal field value initialized with fn call" { - if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO - - const S = struct { - fn doTheTest() !void { - var x = .{foo()}; - try expectEqualSlices(u8, x[0], "hi"); - } - fn foo() []const u8 { - return "hi"; - } - }; - try S.doTheTest(); - comptime try S.doTheTest(); -} - -test "struct with union field" { - if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO - - const Value = struct { - ref: u32 = 2, - kind: union(enum) { - None: usize, - Bool: bool, - }, - }; - - var True = Value{ - .kind = .{ .Bool = true }, - }; - try expectEqual(@as(u32, 2), True.ref); - try expectEqual(true, True.kind.Bool); -} - -test "type coercion of anon struct literal to struct" { - if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO - - const S = struct { - const S2 = struct { - A: u32, - B: []const u8, - C: void, - D: Foo = .{}, - }; - - const Foo = struct { - field: i32 = 1234, - }; - - fn doTheTest() !void { - var y: u32 = 42; - const t0 = .{ .A = 123, .B = "foo", .C = {} }; - const t1 = .{ .A = y, .B = "foo", .C = {} }; - const y0: S2 = t0; - var y1: S2 = t1; - try expect(y0.A == 123); - try expect(std.mem.eql(u8, y0.B, "foo")); - try expect(y0.C == {}); - try expect(y0.D.field == 1234); - try expect(y1.A == y); - try expect(std.mem.eql(u8, y1.B, "foo")); - try expect(y1.C == {}); - try expect(y1.D.field == 1234); - } - }; - try S.doTheTest(); - comptime try S.doTheTest(); -} - -test "type coercion of pointer to anon struct literal to pointer to struct" { - if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO - - const S = struct { - const S2 = struct { - A: u32, - B: []const u8, - C: void, - D: Foo = .{}, - }; - - const Foo = struct { - field: i32 = 1234, - }; - - fn doTheTest() !void { - var y: u32 = 42; - const t0 = &.{ .A = 123, .B = "foo", .C = {} }; - const t1 = &.{ .A = y, .B = "foo", .C = {} }; - const y0: *const S2 = t0; - var y1: *const S2 = t1; - try expect(y0.A == 123); - try expect(std.mem.eql(u8, y0.B, "foo")); - try expect(y0.C == {}); - try expect(y0.D.field == 1234); - try expect(y1.A == y); - try expect(std.mem.eql(u8, y1.B, "foo")); - try expect(y1.C == {}); - try expect(y1.D.field == 1234); - } - }; - try S.doTheTest(); - comptime try S.doTheTest(); -} - -test "packed struct with undefined initializers" { - const S = struct { - const P = packed struct { - a: u3, - _a: u3 = undefined, - b: u3, - _b: u3 = undefined, - c: u3, - _c: u3 = undefined, - }; - - fn doTheTest() !void { - var p: P = undefined; - p = P{ .a = 2, .b = 4, .c = 6 }; - // Make sure the compiler doesn't touch the unprefixed fields. - // Use expect since i386-linux doesn't like expectEqual - try expect(p.a == 2); - try expect(p.b == 4); - try expect(p.c == 6); - } - }; - - try S.doTheTest(); - comptime try S.doTheTest(); -} - -test "for loop over pointers to struct, getting field from struct pointer" { - // When enabling this test, be careful. I have observed it to pass when compiling - // stage2 alone, but when using stage1 with -fno-stage1 -fLLVM it fails. - // Maybe eyeball the LLVM that it generates and run in valgrind, both the compiler - // and the generated test at runtime. - if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO - - const S = struct { - const Foo = struct { - name: []const u8, - }; - - var ok = true; - - fn eql(a: []const u8) bool { - _ = a; - return true; - } - - const ArrayList = struct { - fn toSlice(self: *ArrayList) []*Foo { - _ = self; - return @as([*]*Foo, undefined)[0..0]; - } - }; - - fn doTheTest() !void { - var objects: ArrayList = undefined; - - for (objects.toSlice()) |obj| { - if (eql(obj.name)) { - ok = false; - } - } - - try expect(ok); - } - }; - try S.doTheTest(); -} diff --git a/test/behavior/truncate.zig b/test/behavior/truncate.zig index ae3e11c929..001ba538b2 100644 --- a/test/behavior/truncate.zig +++ b/test/behavior/truncate.zig @@ -76,3 +76,16 @@ test "truncate on comptime integer" { var w = @truncate(u1, 1 << 100); try expect(w == 0); } + +test "truncate on vectors" { + if (builtin.zig_backend != .stage1) return error.SkipZigTest; + + const S = struct { + fn doTheTest() !void { + var v1: @Vector(4, u16) = .{ 0xaabb, 0xccdd, 0xeeff, 0x1122 }; + var v2 = @truncate(u8, v1); + try expect(std.mem.eql(u8, &@as([4]u8, v2), &[4]u8{ 0xbb, 0xdd, 0xff, 0x22 })); + } + }; + try S.doTheTest(); +} diff --git a/test/behavior/truncate_stage1.zig b/test/behavior/truncate_stage1.zig deleted file mode 100644 index 5c66085cbb..0000000000 --- a/test/behavior/truncate_stage1.zig +++ /dev/null @@ -1,13 +0,0 @@ -const std = @import("std"); -const expect = std.testing.expect; - -test "truncate on vectors" { - const S = struct { - fn doTheTest() !void { - var v1: @Vector(4, u16) = .{ 0xaabb, 0xccdd, 0xeeff, 0x1122 }; - var v2 = @truncate(u8, v1); - try expect(std.mem.eql(u8, &@as([4]u8, v2), &[4]u8{ 0xbb, 0xdd, 0xff, 0x22 })); - } - }; - try S.doTheTest(); -} diff --git a/test/behavior/type.zig b/test/behavior/type.zig index cb72f86b8b..60d4463873 100644 --- a/test/behavior/type.zig +++ b/test/behavior/type.zig @@ -102,3 +102,389 @@ test "Type.Pointer" { [*c]align(8) volatile u8, [*c]align(8) const volatile u8, }); } + +test "Type.Float" { + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + + try testing.expect(f16 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 16 } })); + try testing.expect(f32 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 32 } })); + try testing.expect(f64 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 64 } })); + try testing.expect(f80 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 80 } })); + try testing.expect(f128 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 128 } })); + try testTypes(&[_]type{ f16, f32, f64, f80, f128 }); +} + +test "Type.Array" { + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + + try testing.expect([123]u8 == @Type(TypeInfo{ + .Array = TypeInfo.Array{ + .len = 123, + .child = u8, + .sentinel = null, + }, + })); + try testing.expect([2]u32 == @Type(TypeInfo{ + .Array = TypeInfo.Array{ + .len = 2, + .child = u32, + .sentinel = null, + }, + })); + try testing.expect([2:0]u32 == @Type(TypeInfo{ + .Array = TypeInfo.Array{ + .len = 2, + .child = u32, + .sentinel = &@as(u32, 0), + }, + })); + try testTypes(&[_]type{ [1]u8, [30]usize, [7]bool }); +} + +test "@Type create slice with null sentinel" { + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + + const Slice = @Type(TypeInfo{ + .Pointer = .{ + .size = .Slice, + .is_const = true, + .is_volatile = false, + .is_allowzero = false, + .alignment = 8, + .address_space = .generic, + .child = *i32, + .sentinel = null, + }, + }); + try testing.expect(Slice == []align(8) const *i32); +} + +test "@Type picks up the sentinel value from TypeInfo" { + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + + try testTypes(&[_]type{ + [11:0]u8, [4:10]u8, + [*:0]u8, [*:0]const u8, + [*:0]volatile u8, [*:0]const volatile u8, + [*:0]align(4) u8, [*:0]align(4) const u8, + [*:0]align(4) volatile u8, [*:0]align(4) const volatile u8, + [*:0]align(8) u8, [*:0]align(8) const u8, + [*:0]align(8) volatile u8, [*:0]align(8) const volatile u8, + [*:0]allowzero u8, [*:0]allowzero const u8, + [*:0]allowzero volatile u8, [*:0]allowzero const volatile u8, + [*:0]allowzero align(4) u8, [*:0]allowzero align(4) const u8, + [*:0]allowzero align(4) volatile u8, [*:0]allowzero align(4) const volatile u8, + [*:5]allowzero align(4) volatile u8, [*:5]allowzero align(4) const volatile u8, + [:0]u8, [:0]const u8, + [:0]volatile u8, [:0]const volatile u8, + [:0]align(4) u8, [:0]align(4) const u8, + [:0]align(4) volatile u8, [:0]align(4) const volatile u8, + [:0]align(8) u8, [:0]align(8) const u8, + [:0]align(8) volatile u8, [:0]align(8) const volatile u8, + [:0]allowzero u8, [:0]allowzero const u8, + [:0]allowzero volatile u8, [:0]allowzero const volatile u8, + [:0]allowzero align(4) u8, [:0]allowzero align(4) const u8, + [:0]allowzero align(4) volatile u8, [:0]allowzero align(4) const volatile u8, + [:4]allowzero align(4) volatile u8, [:4]allowzero align(4) const volatile u8, + }); +} + +test "Type.Optional" { + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + + try testTypes(&[_]type{ + ?u8, + ?*u8, + ?[]u8, + ?[*]u8, + ?[*c]u8, + }); +} + +test "Type.ErrorUnion" { + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + + try testTypes(&[_]type{ + error{}!void, + error{Error}!void, + }); +} + +test "Type.Opaque" { + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + + const Opaque = @Type(.{ + .Opaque = .{ + .decls = &[_]TypeInfo.Declaration{}, + }, + }); + try testing.expect(Opaque != opaque {}); + try testing.expectEqualSlices( + TypeInfo.Declaration, + &[_]TypeInfo.Declaration{}, + @typeInfo(Opaque).Opaque.decls, + ); +} + +test "Type.Vector" { + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + + try testTypes(&[_]type{ + @Vector(0, u8), + @Vector(4, u8), + @Vector(8, *u8), + std.meta.Vector(0, u8), + std.meta.Vector(4, u8), + std.meta.Vector(8, *u8), + }); +} + +test "Type.AnyFrame" { + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + + try testTypes(&[_]type{ + anyframe, + anyframe->u8, + anyframe->anyframe->u8, + }); +} + +fn add(a: i32, b: i32) i32 { + return a + b; +} + +test "Type.ErrorSet" { + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + + // error sets don't compare equal so just check if they compile + _ = @Type(@typeInfo(error{})); + _ = @Type(@typeInfo(error{A})); + _ = @Type(@typeInfo(error{ A, B, C })); +} + +test "Type.Struct" { + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + + const A = @Type(@typeInfo(struct { x: u8, y: u32 })); + const infoA = @typeInfo(A).Struct; + try testing.expectEqual(TypeInfo.ContainerLayout.Auto, infoA.layout); + try testing.expectEqualSlices(u8, "x", infoA.fields[0].name); + try testing.expectEqual(u8, infoA.fields[0].field_type); + try testing.expectEqual(@as(?*const anyopaque, null), infoA.fields[0].default_value); + try testing.expectEqualSlices(u8, "y", infoA.fields[1].name); + try testing.expectEqual(u32, infoA.fields[1].field_type); + try testing.expectEqual(@as(?*const anyopaque, null), infoA.fields[1].default_value); + try testing.expectEqualSlices(TypeInfo.Declaration, &[_]TypeInfo.Declaration{}, infoA.decls); + try testing.expectEqual(@as(bool, false), infoA.is_tuple); + + var a = A{ .x = 0, .y = 1 }; + try testing.expectEqual(@as(u8, 0), a.x); + try testing.expectEqual(@as(u32, 1), a.y); + a.y += 1; + try testing.expectEqual(@as(u32, 2), a.y); + + const B = @Type(@typeInfo(extern struct { x: u8, y: u32 = 5 })); + const infoB = @typeInfo(B).Struct; + try testing.expectEqual(TypeInfo.ContainerLayout.Extern, infoB.layout); + try testing.expectEqualSlices(u8, "x", infoB.fields[0].name); + try testing.expectEqual(u8, infoB.fields[0].field_type); + try testing.expectEqual(@as(?*const anyopaque, null), infoB.fields[0].default_value); + try testing.expectEqualSlices(u8, "y", infoB.fields[1].name); + try testing.expectEqual(u32, infoB.fields[1].field_type); + try testing.expectEqual(@as(u32, 5), @ptrCast(*const u32, infoB.fields[1].default_value.?).*); + try testing.expectEqual(@as(usize, 0), infoB.decls.len); + try testing.expectEqual(@as(bool, false), infoB.is_tuple); + + const C = @Type(@typeInfo(packed struct { x: u8 = 3, y: u32 = 5 })); + const infoC = @typeInfo(C).Struct; + try testing.expectEqual(TypeInfo.ContainerLayout.Packed, infoC.layout); + try testing.expectEqualSlices(u8, "x", infoC.fields[0].name); + try testing.expectEqual(u8, infoC.fields[0].field_type); + try testing.expectEqual(@as(u8, 3), @ptrCast(*const u8, infoC.fields[0].default_value.?).*); + try testing.expectEqualSlices(u8, "y", infoC.fields[1].name); + try testing.expectEqual(u32, infoC.fields[1].field_type); + try testing.expectEqual(@as(u32, 5), @ptrCast(*const u32, infoC.fields[1].default_value.?).*); + try testing.expectEqual(@as(usize, 0), infoC.decls.len); + try testing.expectEqual(@as(bool, false), infoC.is_tuple); +} + +test "Type.Enum" { + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + + const Foo = @Type(.{ + .Enum = .{ + .layout = .Auto, + .tag_type = u8, + .fields = &[_]TypeInfo.EnumField{ + .{ .name = "a", .value = 1 }, + .{ .name = "b", .value = 5 }, + }, + .decls = &[_]TypeInfo.Declaration{}, + .is_exhaustive = true, + }, + }); + try testing.expectEqual(true, @typeInfo(Foo).Enum.is_exhaustive); + try testing.expectEqual(@as(u8, 1), @enumToInt(Foo.a)); + try testing.expectEqual(@as(u8, 5), @enumToInt(Foo.b)); + const Bar = @Type(.{ + .Enum = .{ + .layout = .Extern, + .tag_type = u32, + .fields = &[_]TypeInfo.EnumField{ + .{ .name = "a", .value = 1 }, + .{ .name = "b", .value = 5 }, + }, + .decls = &[_]TypeInfo.Declaration{}, + .is_exhaustive = false, + }, + }); + try testing.expectEqual(false, @typeInfo(Bar).Enum.is_exhaustive); + try testing.expectEqual(@as(u32, 1), @enumToInt(Bar.a)); + try testing.expectEqual(@as(u32, 5), @enumToInt(Bar.b)); + try testing.expectEqual(@as(u32, 6), @enumToInt(@intToEnum(Bar, 6))); +} + +test "Type.Union" { + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + + const Untagged = @Type(.{ + .Union = .{ + .layout = .Auto, + .tag_type = null, + .fields = &[_]TypeInfo.UnionField{ + .{ .name = "int", .field_type = i32, .alignment = @alignOf(f32) }, + .{ .name = "float", .field_type = f32, .alignment = @alignOf(f32) }, + }, + .decls = &[_]TypeInfo.Declaration{}, + }, + }); + var untagged = Untagged{ .int = 1 }; + untagged.float = 2.0; + untagged.int = 3; + try testing.expectEqual(@as(i32, 3), untagged.int); + + const PackedUntagged = @Type(.{ + .Union = .{ + .layout = .Packed, + .tag_type = null, + .fields = &[_]TypeInfo.UnionField{ + .{ .name = "signed", .field_type = i32, .alignment = @alignOf(i32) }, + .{ .name = "unsigned", .field_type = u32, .alignment = @alignOf(u32) }, + }, + .decls = &[_]TypeInfo.Declaration{}, + }, + }); + var packed_untagged = PackedUntagged{ .signed = -1 }; + try testing.expectEqual(@as(i32, -1), packed_untagged.signed); + try testing.expectEqual(~@as(u32, 0), packed_untagged.unsigned); + + const Tag = @Type(.{ + .Enum = .{ + .layout = .Auto, + .tag_type = u1, + .fields = &[_]TypeInfo.EnumField{ + .{ .name = "signed", .value = 0 }, + .{ .name = "unsigned", .value = 1 }, + }, + .decls = &[_]TypeInfo.Declaration{}, + .is_exhaustive = true, + }, + }); + const Tagged = @Type(.{ + .Union = .{ + .layout = .Auto, + .tag_type = Tag, + .fields = &[_]TypeInfo.UnionField{ + .{ .name = "signed", .field_type = i32, .alignment = @alignOf(i32) }, + .{ .name = "unsigned", .field_type = u32, .alignment = @alignOf(u32) }, + }, + .decls = &[_]TypeInfo.Declaration{}, + }, + }); + var tagged = Tagged{ .signed = -1 }; + try testing.expectEqual(Tag.signed, tagged); + tagged = .{ .unsigned = 1 }; + try testing.expectEqual(Tag.unsigned, tagged); +} + +test "Type.Union from Type.Enum" { + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + + const Tag = @Type(.{ + .Enum = .{ + .layout = .Auto, + .tag_type = u0, + .fields = &[_]TypeInfo.EnumField{ + .{ .name = "working_as_expected", .value = 0 }, + }, + .decls = &[_]TypeInfo.Declaration{}, + .is_exhaustive = true, + }, + }); + const T = @Type(.{ + .Union = .{ + .layout = .Auto, + .tag_type = Tag, + .fields = &[_]TypeInfo.UnionField{ + .{ .name = "working_as_expected", .field_type = u32, .alignment = @alignOf(u32) }, + }, + .decls = &[_]TypeInfo.Declaration{}, + }, + }); + _ = T; + _ = @typeInfo(T).Union; +} + +test "Type.Union from regular enum" { + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + + const E = enum { working_as_expected }; + const T = @Type(.{ + .Union = .{ + .layout = .Auto, + .tag_type = E, + .fields = &[_]TypeInfo.UnionField{ + .{ .name = "working_as_expected", .field_type = u32, .alignment = @alignOf(u32) }, + }, + .decls = &[_]TypeInfo.Declaration{}, + }, + }); + _ = T; + _ = @typeInfo(T).Union; +} + +test "Type.Fn" { + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + + // wasm doesn't support align attributes on functions + if (builtin.target.cpu.arch == .wasm32 or builtin.target.cpu.arch == .wasm64) return error.SkipZigTest; + + const foo = struct { + fn func(a: usize, b: bool) align(4) callconv(.C) usize { + _ = a; + _ = b; + return 0; + } + }.func; + const Foo = @Type(@typeInfo(@TypeOf(foo))); + const foo_2: Foo = foo; + _ = foo_2; +} + +test "Type.BoundFn" { + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + + // wasm doesn't support align attributes on functions + if (builtin.target.cpu.arch == .wasm32 or builtin.target.cpu.arch == .wasm64) return error.SkipZigTest; + + const TestStruct = packed struct { + pub fn foo(self: *const @This()) align(4) callconv(.Unspecified) void { + _ = self; + } + }; + const test_instance: TestStruct = undefined; + try testing.expect(std.meta.eql( + @typeName(@TypeOf(test_instance.foo)), + @typeName(@Type(@typeInfo(@TypeOf(test_instance.foo)))), + )); +} diff --git a/test/behavior/type_stage1.zig b/test/behavior/type_stage1.zig deleted file mode 100644 index 852c9fc82d..0000000000 --- a/test/behavior/type_stage1.zig +++ /dev/null @@ -1,362 +0,0 @@ -const std = @import("std"); -const builtin = @import("builtin"); -const TypeInfo = std.builtin.TypeInfo; -const testing = std.testing; - -fn testTypes(comptime types: []const type) !void { - inline for (types) |testType| { - try testing.expect(testType == @Type(@typeInfo(testType))); - } -} - -test "Type.Float" { - try testing.expect(f16 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 16 } })); - try testing.expect(f32 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 32 } })); - try testing.expect(f64 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 64 } })); - try testing.expect(f80 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 80 } })); - try testing.expect(f128 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 128 } })); - try testTypes(&[_]type{ f16, f32, f64, f80, f128 }); -} - -test "Type.Array" { - try testing.expect([123]u8 == @Type(TypeInfo{ - .Array = TypeInfo.Array{ - .len = 123, - .child = u8, - .sentinel = null, - }, - })); - try testing.expect([2]u32 == @Type(TypeInfo{ - .Array = TypeInfo.Array{ - .len = 2, - .child = u32, - .sentinel = null, - }, - })); - try testing.expect([2:0]u32 == @Type(TypeInfo{ - .Array = TypeInfo.Array{ - .len = 2, - .child = u32, - .sentinel = &@as(u32, 0), - }, - })); - try testTypes(&[_]type{ [1]u8, [30]usize, [7]bool }); -} - -test "@Type create slice with null sentinel" { - const Slice = @Type(TypeInfo{ - .Pointer = .{ - .size = .Slice, - .is_const = true, - .is_volatile = false, - .is_allowzero = false, - .alignment = 8, - .address_space = .generic, - .child = *i32, - .sentinel = null, - }, - }); - try testing.expect(Slice == []align(8) const *i32); -} - -test "@Type picks up the sentinel value from TypeInfo" { - try testTypes(&[_]type{ - [11:0]u8, [4:10]u8, - [*:0]u8, [*:0]const u8, - [*:0]volatile u8, [*:0]const volatile u8, - [*:0]align(4) u8, [*:0]align(4) const u8, - [*:0]align(4) volatile u8, [*:0]align(4) const volatile u8, - [*:0]align(8) u8, [*:0]align(8) const u8, - [*:0]align(8) volatile u8, [*:0]align(8) const volatile u8, - [*:0]allowzero u8, [*:0]allowzero const u8, - [*:0]allowzero volatile u8, [*:0]allowzero const volatile u8, - [*:0]allowzero align(4) u8, [*:0]allowzero align(4) const u8, - [*:0]allowzero align(4) volatile u8, [*:0]allowzero align(4) const volatile u8, - [*:5]allowzero align(4) volatile u8, [*:5]allowzero align(4) const volatile u8, - [:0]u8, [:0]const u8, - [:0]volatile u8, [:0]const volatile u8, - [:0]align(4) u8, [:0]align(4) const u8, - [:0]align(4) volatile u8, [:0]align(4) const volatile u8, - [:0]align(8) u8, [:0]align(8) const u8, - [:0]align(8) volatile u8, [:0]align(8) const volatile u8, - [:0]allowzero u8, [:0]allowzero const u8, - [:0]allowzero volatile u8, [:0]allowzero const volatile u8, - [:0]allowzero align(4) u8, [:0]allowzero align(4) const u8, - [:0]allowzero align(4) volatile u8, [:0]allowzero align(4) const volatile u8, - [:4]allowzero align(4) volatile u8, [:4]allowzero align(4) const volatile u8, - }); -} - -test "Type.Optional" { - try testTypes(&[_]type{ - ?u8, - ?*u8, - ?[]u8, - ?[*]u8, - ?[*c]u8, - }); -} - -test "Type.ErrorUnion" { - try testTypes(&[_]type{ - error{}!void, - error{Error}!void, - }); -} - -test "Type.Opaque" { - const Opaque = @Type(.{ - .Opaque = .{ - .decls = &[_]TypeInfo.Declaration{}, - }, - }); - try testing.expect(Opaque != opaque {}); - try testing.expectEqualSlices( - TypeInfo.Declaration, - &[_]TypeInfo.Declaration{}, - @typeInfo(Opaque).Opaque.decls, - ); -} - -test "Type.Vector" { - try testTypes(&[_]type{ - @Vector(0, u8), - @Vector(4, u8), - @Vector(8, *u8), - std.meta.Vector(0, u8), - std.meta.Vector(4, u8), - std.meta.Vector(8, *u8), - }); -} - -test "Type.AnyFrame" { - try testTypes(&[_]type{ - anyframe, - anyframe->u8, - anyframe->anyframe->u8, - }); -} - -fn add(a: i32, b: i32) i32 { - return a + b; -} - -test "Type.ErrorSet" { - // error sets don't compare equal so just check if they compile - _ = @Type(@typeInfo(error{})); - _ = @Type(@typeInfo(error{A})); - _ = @Type(@typeInfo(error{ A, B, C })); -} - -test "Type.Struct" { - const A = @Type(@typeInfo(struct { x: u8, y: u32 })); - const infoA = @typeInfo(A).Struct; - try testing.expectEqual(TypeInfo.ContainerLayout.Auto, infoA.layout); - try testing.expectEqualSlices(u8, "x", infoA.fields[0].name); - try testing.expectEqual(u8, infoA.fields[0].field_type); - try testing.expectEqual(@as(?*const anyopaque, null), infoA.fields[0].default_value); - try testing.expectEqualSlices(u8, "y", infoA.fields[1].name); - try testing.expectEqual(u32, infoA.fields[1].field_type); - try testing.expectEqual(@as(?*const anyopaque, null), infoA.fields[1].default_value); - try testing.expectEqualSlices(TypeInfo.Declaration, &[_]TypeInfo.Declaration{}, infoA.decls); - try testing.expectEqual(@as(bool, false), infoA.is_tuple); - - var a = A{ .x = 0, .y = 1 }; - try testing.expectEqual(@as(u8, 0), a.x); - try testing.expectEqual(@as(u32, 1), a.y); - a.y += 1; - try testing.expectEqual(@as(u32, 2), a.y); - - const B = @Type(@typeInfo(extern struct { x: u8, y: u32 = 5 })); - const infoB = @typeInfo(B).Struct; - try testing.expectEqual(TypeInfo.ContainerLayout.Extern, infoB.layout); - try testing.expectEqualSlices(u8, "x", infoB.fields[0].name); - try testing.expectEqual(u8, infoB.fields[0].field_type); - try testing.expectEqual(@as(?*const anyopaque, null), infoB.fields[0].default_value); - try testing.expectEqualSlices(u8, "y", infoB.fields[1].name); - try testing.expectEqual(u32, infoB.fields[1].field_type); - try testing.expectEqual(@as(u32, 5), @ptrCast(*const u32, infoB.fields[1].default_value.?).*); - try testing.expectEqual(@as(usize, 0), infoB.decls.len); - try testing.expectEqual(@as(bool, false), infoB.is_tuple); - - const C = @Type(@typeInfo(packed struct { x: u8 = 3, y: u32 = 5 })); - const infoC = @typeInfo(C).Struct; - try testing.expectEqual(TypeInfo.ContainerLayout.Packed, infoC.layout); - try testing.expectEqualSlices(u8, "x", infoC.fields[0].name); - try testing.expectEqual(u8, infoC.fields[0].field_type); - try testing.expectEqual(@as(u8, 3), @ptrCast(*const u8, infoC.fields[0].default_value.?).*); - try testing.expectEqualSlices(u8, "y", infoC.fields[1].name); - try testing.expectEqual(u32, infoC.fields[1].field_type); - try testing.expectEqual(@as(u32, 5), @ptrCast(*const u32, infoC.fields[1].default_value.?).*); - try testing.expectEqual(@as(usize, 0), infoC.decls.len); - try testing.expectEqual(@as(bool, false), infoC.is_tuple); -} - -test "Type.Enum" { - const Foo = @Type(.{ - .Enum = .{ - .layout = .Auto, - .tag_type = u8, - .fields = &[_]TypeInfo.EnumField{ - .{ .name = "a", .value = 1 }, - .{ .name = "b", .value = 5 }, - }, - .decls = &[_]TypeInfo.Declaration{}, - .is_exhaustive = true, - }, - }); - try testing.expectEqual(true, @typeInfo(Foo).Enum.is_exhaustive); - try testing.expectEqual(@as(u8, 1), @enumToInt(Foo.a)); - try testing.expectEqual(@as(u8, 5), @enumToInt(Foo.b)); - const Bar = @Type(.{ - .Enum = .{ - .layout = .Extern, - .tag_type = u32, - .fields = &[_]TypeInfo.EnumField{ - .{ .name = "a", .value = 1 }, - .{ .name = "b", .value = 5 }, - }, - .decls = &[_]TypeInfo.Declaration{}, - .is_exhaustive = false, - }, - }); - try testing.expectEqual(false, @typeInfo(Bar).Enum.is_exhaustive); - try testing.expectEqual(@as(u32, 1), @enumToInt(Bar.a)); - try testing.expectEqual(@as(u32, 5), @enumToInt(Bar.b)); - try testing.expectEqual(@as(u32, 6), @enumToInt(@intToEnum(Bar, 6))); -} - -test "Type.Union" { - const Untagged = @Type(.{ - .Union = .{ - .layout = .Auto, - .tag_type = null, - .fields = &[_]TypeInfo.UnionField{ - .{ .name = "int", .field_type = i32, .alignment = @alignOf(f32) }, - .{ .name = "float", .field_type = f32, .alignment = @alignOf(f32) }, - }, - .decls = &[_]TypeInfo.Declaration{}, - }, - }); - var untagged = Untagged{ .int = 1 }; - untagged.float = 2.0; - untagged.int = 3; - try testing.expectEqual(@as(i32, 3), untagged.int); - - const PackedUntagged = @Type(.{ - .Union = .{ - .layout = .Packed, - .tag_type = null, - .fields = &[_]TypeInfo.UnionField{ - .{ .name = "signed", .field_type = i32, .alignment = @alignOf(i32) }, - .{ .name = "unsigned", .field_type = u32, .alignment = @alignOf(u32) }, - }, - .decls = &[_]TypeInfo.Declaration{}, - }, - }); - var packed_untagged = PackedUntagged{ .signed = -1 }; - try testing.expectEqual(@as(i32, -1), packed_untagged.signed); - try testing.expectEqual(~@as(u32, 0), packed_untagged.unsigned); - - const Tag = @Type(.{ - .Enum = .{ - .layout = .Auto, - .tag_type = u1, - .fields = &[_]TypeInfo.EnumField{ - .{ .name = "signed", .value = 0 }, - .{ .name = "unsigned", .value = 1 }, - }, - .decls = &[_]TypeInfo.Declaration{}, - .is_exhaustive = true, - }, - }); - const Tagged = @Type(.{ - .Union = .{ - .layout = .Auto, - .tag_type = Tag, - .fields = &[_]TypeInfo.UnionField{ - .{ .name = "signed", .field_type = i32, .alignment = @alignOf(i32) }, - .{ .name = "unsigned", .field_type = u32, .alignment = @alignOf(u32) }, - }, - .decls = &[_]TypeInfo.Declaration{}, - }, - }); - var tagged = Tagged{ .signed = -1 }; - try testing.expectEqual(Tag.signed, tagged); - tagged = .{ .unsigned = 1 }; - try testing.expectEqual(Tag.unsigned, tagged); -} - -test "Type.Union from Type.Enum" { - const Tag = @Type(.{ - .Enum = .{ - .layout = .Auto, - .tag_type = u0, - .fields = &[_]TypeInfo.EnumField{ - .{ .name = "working_as_expected", .value = 0 }, - }, - .decls = &[_]TypeInfo.Declaration{}, - .is_exhaustive = true, - }, - }); - const T = @Type(.{ - .Union = .{ - .layout = .Auto, - .tag_type = Tag, - .fields = &[_]TypeInfo.UnionField{ - .{ .name = "working_as_expected", .field_type = u32, .alignment = @alignOf(u32) }, - }, - .decls = &[_]TypeInfo.Declaration{}, - }, - }); - _ = T; - _ = @typeInfo(T).Union; -} - -test "Type.Union from regular enum" { - const E = enum { working_as_expected }; - const T = @Type(.{ - .Union = .{ - .layout = .Auto, - .tag_type = E, - .fields = &[_]TypeInfo.UnionField{ - .{ .name = "working_as_expected", .field_type = u32, .alignment = @alignOf(u32) }, - }, - .decls = &[_]TypeInfo.Declaration{}, - }, - }); - _ = T; - _ = @typeInfo(T).Union; -} - -test "Type.Fn" { - // wasm doesn't support align attributes on functions - if (builtin.target.cpu.arch == .wasm32 or builtin.target.cpu.arch == .wasm64) return error.SkipZigTest; - - const foo = struct { - fn func(a: usize, b: bool) align(4) callconv(.C) usize { - _ = a; - _ = b; - return 0; - } - }.func; - const Foo = @Type(@typeInfo(@TypeOf(foo))); - const foo_2: Foo = foo; - _ = foo_2; -} - -test "Type.BoundFn" { - // wasm doesn't support align attributes on functions - if (builtin.target.cpu.arch == .wasm32 or builtin.target.cpu.arch == .wasm64) return error.SkipZigTest; - - const TestStruct = packed struct { - pub fn foo(self: *const @This()) align(4) callconv(.Unspecified) void { - _ = self; - } - }; - const test_instance: TestStruct = undefined; - try testing.expect(std.meta.eql( - @typeName(@TypeOf(test_instance.foo)), - @typeName(@Type(@typeInfo(@TypeOf(test_instance.foo)))), - )); -} -- cgit v1.2.3