aboutsummaryrefslogtreecommitdiff
path: root/test/behavior/struct.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2022-02-12 21:13:07 -0700
committerAndrew Kelley <andrew@ziglang.org>2022-02-12 21:13:07 -0700
commitc349191b75811f8a21e26f8b175483449fae1638 (patch)
tree70e4b8e77f3b7746110b7ed0a1b391c189b3f81d /test/behavior/struct.zig
parenta005ac9d3c884c6254074ec150fe536881fe31b5 (diff)
downloadzig-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.zig894
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();
+}