aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authormlugg <mlugg@mlugg.co.uk>2023-09-21 02:00:52 +0100
committerAndrew Kelley <andrew@ziglang.org>2023-09-21 14:48:41 -0700
commit1b672e41c528b0aa225cbe07c61203d04b2d9034 (patch)
tree080cac4fbde495c9b216fac1cd67e84799740059 /test
parentcd242b7440e11d9997c33296b3974dfb1fbd5d95 (diff)
downloadzig-1b672e41c528b0aa225cbe07c61203d04b2d9034.tar.gz
zig-1b672e41c528b0aa225cbe07c61203d04b2d9034.zip
InternPool,Sema,type,llvm: alignment fixes
This changeset fixes the handling of alignment in several places. The new rules are: * `@alignOf(T)` where `T` is a runtime zero-bit type is at least 1, maybe greater. * Zero-bit fields in `extern` structs *do* force alignment, potentially offsetting following fields. * Zero-bit fields *do* have addresses within structs which can be observed and are consistent with `@offsetOf`. These are not necessarily all implemented correctly yet (see disabled test), but this commit fixes all regressions compared to master, and makes one new test pass.
Diffstat (limited to 'test')
-rw-r--r--test/behavior/align.zig55
-rw-r--r--test/behavior/alignof.zig25
-rw-r--r--test/behavior/empty_union.zig2
3 files changed, 63 insertions, 19 deletions
diff --git a/test/behavior/align.zig b/test/behavior/align.zig
index e1a8fb8e98..c33f685325 100644
--- a/test/behavior/align.zig
+++ b/test/behavior/align.zig
@@ -619,3 +619,58 @@ test "sub-aligned pointer field access" {
.Little => try expect(x == 0x09080706),
}
}
+
+test "alignment of zero-bit types is respected" {
+ if (true) return error.SkipZigTest; // TODO
+
+ const S = struct { arr: [0]usize = .{} };
+
+ comptime assert(@alignOf(void) == 1);
+ comptime assert(@alignOf(u0) == 1);
+ comptime assert(@alignOf([0]usize) == @alignOf(usize));
+ comptime assert(@alignOf(S) == @alignOf(usize));
+
+ var s: S = .{};
+ var v32: void align(32) = {};
+ var x32: u0 align(32) = 0;
+ var s32: S align(32) = .{};
+
+ var zero: usize = 0;
+
+ try expect(@intFromPtr(&s) % @alignOf(usize) == 0);
+ try expect(@intFromPtr(&s.arr) % @alignOf(usize) == 0);
+ try expect(@intFromPtr(s.arr[zero..zero].ptr) % @alignOf(usize) == 0);
+ try expect(@intFromPtr(&v32) % 32 == 0);
+ try expect(@intFromPtr(&x32) % 32 == 0);
+ try expect(@intFromPtr(&s32) % 32 == 0);
+ try expect(@intFromPtr(&s32.arr) % 32 == 0);
+ try expect(@intFromPtr(s32.arr[zero..zero].ptr) % 32 == 0);
+}
+
+test "zero-bit fields in extern struct pad fields appropriately" {
+ if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
+
+ const S = extern struct {
+ x: u8,
+ a: [0]u16 = .{},
+ y: u8,
+ };
+
+ // `a` should give `S` alignment 2, and pad the `arr` field.
+ comptime assert(@alignOf(S) == 2);
+ comptime assert(@sizeOf(S) == 4);
+ comptime assert(@offsetOf(S, "x") == 0);
+ comptime assert(@offsetOf(S, "a") == 2);
+ comptime assert(@offsetOf(S, "y") == 2);
+
+ var s: S = .{ .x = 100, .y = 200 };
+
+ try expect(@intFromPtr(&s) % 2 == 0);
+ try expect(@intFromPtr(&s.y) - @intFromPtr(&s.x) == 2);
+ try expect(@intFromPtr(&s.y) == @intFromPtr(&s.a));
+ try expect(@fieldParentPtr(S, "a", &s.a) == &s);
+}
diff --git a/test/behavior/alignof.zig b/test/behavior/alignof.zig
index b414b7e056..0443b2d6b3 100644
--- a/test/behavior/alignof.zig
+++ b/test/behavior/alignof.zig
@@ -18,24 +18,13 @@ test "@alignOf(T) before referencing T" {
}
test "comparison of @alignOf(T) against zero" {
- {
- const T = struct { x: u32 };
- try expect(!(@alignOf(T) == 0));
- try expect(@alignOf(T) != 0);
- try expect(!(@alignOf(T) < 0));
- try expect(!(@alignOf(T) <= 0));
- try expect(@alignOf(T) > 0);
- try expect(@alignOf(T) >= 0);
- }
- {
- const T = struct {};
- try expect(@alignOf(T) == 0);
- try expect(!(@alignOf(T) != 0));
- try expect(!(@alignOf(T) < 0));
- try expect(@alignOf(T) <= 0);
- try expect(!(@alignOf(T) > 0));
- try expect(@alignOf(T) >= 0);
- }
+ const T = struct { x: u32 };
+ try expect(!(@alignOf(T) == 0));
+ try expect(@alignOf(T) != 0);
+ try expect(!(@alignOf(T) < 0));
+ try expect(!(@alignOf(T) <= 0));
+ try expect(@alignOf(T) > 0);
+ try expect(@alignOf(T) >= 0);
}
test "correct alignment for elements and slices of aligned array" {
diff --git a/test/behavior/empty_union.zig b/test/behavior/empty_union.zig
index 1bdbf8e54b..16606b5785 100644
--- a/test/behavior/empty_union.zig
+++ b/test/behavior/empty_union.zig
@@ -37,7 +37,7 @@ test "switch on empty tagged union" {
test "empty union" {
const U = union {};
try expect(@sizeOf(U) == 0);
- try expect(@alignOf(U) == 0);
+ try expect(@alignOf(U) == 1);
}
test "empty extern union" {