aboutsummaryrefslogtreecommitdiff
path: root/test/behavior/struct.zig
diff options
context:
space:
mode:
Diffstat (limited to 'test/behavior/struct.zig')
-rw-r--r--test/behavior/struct.zig252
1 files changed, 238 insertions, 14 deletions
diff --git a/test/behavior/struct.zig b/test/behavior/struct.zig
index 7eb5e62282..d03e4ebf32 100644
--- a/test/behavior/struct.zig
+++ b/test/behavior/struct.zig
@@ -203,18 +203,18 @@ test "return struct byval from function" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
- const bar = makeBar2(1234, 5678);
- try expect(bar.y == 5678);
-}
-const Bar = struct {
- x: i32,
- y: i32,
-};
-fn makeBar2(x: i32, y: i32) Bar {
- return Bar{
- .x = x,
- .y = y,
+ const Bar = struct {
+ x: i32,
+ y: i32,
+ fn makeBar2(x: i32, y: i32) @This() {
+ return .{
+ .x = x,
+ .y = y,
+ };
+ }
};
+ const bar = Bar.makeBar2(1234, 5678);
+ try expect(bar.y == 5678);
}
test "call method with mutable reference to struct with no fields" {
@@ -1883,10 +1883,234 @@ test "field calls do not force struct field init resolution" {
}
test "tuple with comptime-only field" {
- const x = getTuple();
+ const S = struct {
+ fn getTuple() struct { comptime_int } {
+ return struct { comptime comptime_int = 0 }{0};
+ }
+ };
+
+ const x = S.getTuple();
try expect(x.@"0" == 0);
}
-fn getTuple() struct { comptime_int } {
- return struct { comptime comptime_int = 0 }{0};
+test "extern struct fields are aligned to 1" {
+ if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
+
+ const Foo = extern struct {
+ a: u8 align(1),
+ b: u16 align(1),
+ };
+
+ const foo = Foo{
+ .a = 1,
+ .b = 2,
+ };
+ try std.testing.expectEqual(1, foo.a);
+ try std.testing.expectEqual(2, foo.b);
+}
+
+test "assign to slice.len of global variable" {
+ if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
+
+ const S = struct {
+ const allocator = std.testing.allocator;
+ var list = std.ArrayList(u32).init(allocator);
+ };
+
+ S.list.items.len = 0;
+ try expect(S.list.items.len == 0);
+}
+
+test "pointers to fields of volatile pointer to struct are also volatile" {
+ const B = extern struct {
+ a: u32,
+ b: i32,
+ };
+ const A = extern struct {
+ value: *volatile B,
+ };
+
+ var a: *A = undefined;
+ try expect(@TypeOf(&a.value.a) == *volatile u32);
+ try expect(@TypeOf(&a.value.b) == *volatile i32);
+}
+
+test "pointers to fields of volatile pointer to union are also volatile" {
+ const D = extern union {
+ a: u32,
+ b: i32,
+ };
+ const C = extern struct {
+ value: *volatile D,
+ };
+
+ var c: *C = undefined;
+ try expect(@TypeOf(&c.value.a) == *volatile u32);
+ try expect(@TypeOf(&c.value.b) == *volatile i32);
+}
+
+test "array of structs inside struct initialized with undefined" {
+ const Item = struct { field: u8 };
+ const Thing = struct {
+ array: [1]Item,
+ };
+ _ = Thing{ .array = undefined };
+}
+
+test "runtime call in nested initializer" {
+ if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
+
+ const Holder = struct {
+ array: []const u8,
+ };
+ const Test = struct {
+ holders: []const Holder,
+ };
+ const Letter = enum(u8) {
+ A = 0x41,
+ B,
+
+ fn letter(e: @This()) u8 {
+ return @intFromEnum(e);
+ }
+ };
+
+ const test_struct = Test{
+ .holders = &.{
+ Holder{
+ .array = &.{
+ Letter.letter(.A),
+ },
+ },
+ },
+ };
+ try std.testing.expectEqualStrings("A", test_struct.holders[0].array);
+}
+
+test "runtime value in nested initializer passed as pointer to function" {
+ if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
+
+ const Bar = struct {
+ b: u32,
+ };
+ const Foo = struct {
+ a: Bar,
+
+ fn takeFoo(foo: *const @This()) !void {
+ try std.testing.expectEqual(@as(u32, 24), foo.a.b);
+ }
+ };
+
+ var baz: u32 = 24;
+ _ = &baz;
+ try Foo.takeFoo(&.{
+ .a = .{
+ .b = baz,
+ },
+ });
+}
+
+test "struct field default value is a call" {
+ if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
+
+ const Z = packed struct {
+ a: u32,
+ };
+ const Y = struct {
+ a: u16,
+ b: bool,
+ c: Z,
+ d: Z,
+
+ fn init() @This() {
+ return .{
+ .a = 0,
+ .b = false,
+ .c = @as(Z, @bitCast(@as(u32, 0))),
+ .d = @as(Z, @bitCast(@as(u32, 0))),
+ };
+ }
+ };
+ const X = struct {
+ y: Y = Y.init(),
+ };
+
+ const x = X{};
+ try std.testing.expectEqual(@as(u16, 0), x.y.a);
+ try std.testing.expectEqual(false, x.y.b);
+ try std.testing.expectEqual(Z{ .a = 0 }, x.y.c);
+ try std.testing.expectEqual(Z{ .a = 0 }, x.y.d);
+}
+
+test "aggregate initializers should allow initializing comptime fields, verifying equality" {
+ var x: u32 = 15;
+ _ = &x;
+ const T = @TypeOf(.{ @as(i32, -1234), @as(u32, 5678), x });
+ const a: T = .{ -1234, 5678, x + 1 };
+
+ try expect(a[0] == -1234);
+ try expect(a[1] == 5678);
+ try expect(a[2] == 16);
+}
+
+test "assignment of field with padding" {
+ if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+
+ const Mesh = extern struct {
+ id: u32,
+ };
+ const Material = extern struct {
+ transparent: bool = true,
+ emits_shadows: bool = true,
+ render_color: bool = true,
+ };
+ const Renderable = extern struct {
+ material: Material,
+ mesh: Mesh,
+ };
+ var renderable: Renderable = undefined;
+ renderable = Renderable{
+ .mesh = Mesh{ .id = 0 },
+ .material = Material{
+ .transparent = false,
+ .emits_shadows = false,
+ },
+ };
+ try expect(false == renderable.material.transparent);
+ try expect(false == renderable.material.emits_shadows);
+ try expect(true == renderable.material.render_color);
+}
+
+test "initiate global variable with runtime value" {
+ if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+
+ const S = struct {
+ field: i32,
+ fn couldFail() anyerror!i32 {
+ return 1;
+ }
+ var some_struct: @This() = undefined;
+ };
+
+ S.some_struct = .{
+ .field = S.couldFail() catch 0,
+ };
+ try expect(S.some_struct.field == 1);
}