diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2022-02-12 21:13:07 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2022-02-12 21:13:07 -0700 |
| commit | c349191b75811f8a21e26f8b175483449fae1638 (patch) | |
| tree | 70e4b8e77f3b7746110b7ed0a1b391c189b3f81d /test/behavior/struct.zig | |
| parent | a005ac9d3c884c6254074ec150fe536881fe31b5 (diff) | |
| download | zig-c349191b75811f8a21e26f8b175483449fae1638.tar.gz zig-c349191b75811f8a21e26f8b175483449fae1638.zip | |
organize behavior tests
moving towards disabling failing tests on an individual basis
Diffstat (limited to 'test/behavior/struct.zig')
| -rw-r--r-- | test/behavior/struct.zig | 894 |
1 files changed, 885 insertions, 9 deletions
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(); +} |
