-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Incorrect behaviour when writing to a field of a packed union that is not a multiple of 8 bits #17360
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
The issue title says Assuming that it's for EDIT: The one issue / ambiguity with this code I see is that all IMO to be 100% conformant to current langref you have to wrap each field in const std = @import("std");
const testing = std.testing;
const U = packed union {
const Foo = packed struct {
value: u12,
keep_the_same: u52,
};
const Bar = packed struct {
value: u29,
keep_the_same: u35,
};
foo: Foo,
bar: Bar,
baz: u64,
};
fn expectations(u: U) !void {
try testing.expectEqual(@as(u12, 0xeee), u.foo.value);
try testing.expectEqual(@as(u29, 0x1bbbbeee), u.bar.value);
try testing.expectEqual(@as(u64, 0xbbbbbbbb_bbbbbeee), u.baz);
}
test "works" {
var u: U = undefined;
u.baz = 0xbbbbbbbb_bbbbbbbb;
u.foo.value = 0xeee;
try expectations(u);
}
test "extra-pedantic" {
var u: U = undefined;
u = .{ .baz = 0xbbbbbbbb_bbbbbbbb };
u = .{ .foo = @bitCast(u) };
u.foo.value = 0xeee;
try expectations(u);
} These modified tests actually pass for me with version |
Ah, yes I misnamed the issue, fixed. Indeed, that is what is happening, it's storing a u16 there. I was confused about the intended behaviour of this as well, but Andrew clarified that it should just be overwriting the 12 least significant bits. |
verbatim message for transparency without Discord access:
The current semantics value speed over preserving padding bits Although, since there are actually two syntactic variants of writing this: u.foo = 0xeee; //(1) overwrite an inactive tag of the union
u = .{.foo = 0xeee}; //(2) overwrite the union with a new value holding a different tag Syntactically (2) assigns "the whole union", while (1) can be interpreted to "only touch the bits of field Would that be acceptable? |
This reminds me, there is an additional odd behaviour I noticed while working on #17352, which was that the |
Zig Version
0.12.0-dev.700+376242e58
Steps to Reproduce and Observed Behavior
Expected is
0x1bbbbeee
, but the actual value is0x1bbb0eee
. The failure also occurs in the x86_64 backend (-fno-llvm -fno-lld
).I confirmed with a debugger this is on the write side of things, after
foo
is written, the backing memory contains0xbbbbbbbbbbbb0eee
.Expected Behavior
Test passes.
The text was updated successfully, but these errors were encountered: