authorgravatar for jay@jayschwa.netJay Petacat <jay@jayschwa.net> 2023-09-29 23:33:50-06:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-10-01 02:39:05-07:00
logd8bfbbbf25984cfdc4d50a92569523a0a151d9e6
tree9452421ad52e61f36cc4090f2edc56285d313bfa
parent376242e586a04b1d2f8f30a329eba3275e0e3a87

std.mem.zeroes: Zero out entire `extern union`, including padding

Fixes #17258

1 files changed, 12 insertions(+), 7 deletions(-)

lib/std/mem.zig+12-7
......@@ -254,7 +254,7 @@ pub fn zeroes(comptime T: type) T {
254254 var structure: T = undefined;
255255 inline for (struct_info.fields) |field| {
256256 if (!field.is_comptime) {
257 @field(structure, field.name) = zeroes(@TypeOf(@field(structure, field.name)));
257 @field(structure, field.name) = zeroes(field.type);
258258 }
259259 }
260260 return structure;
......@@ -292,12 +292,11 @@ pub fn zeroes(comptime T: type) T {
292292 return @splat(zeroes(info.child));
293293 },
294294 .Union => |info| {
295 if (comptime meta.containerLayout(T) == .Extern) {
296 // The C language specification states that (global) unions
297 // should be zero initialized to the first named member.
298 return @unionInit(T, info.fields[0].name, zeroes(info.fields[0].type));
295 if (info.layout == .Extern) {
296 var item: T = undefined;
297 @memset(asBytes(&item), 0);
298 return item;
299299 }
300
301300 @compileError("Can't set a " ++ @typeName(T) ++ " to zero.");
302301 },
303302 .ErrorUnion,
......@@ -318,10 +317,14 @@ pub fn zeroes(comptime T: type) T {
318317test "zeroes" {
319318 const C_struct = extern struct {
320319 x: u32,
321 y: u32,
320 y: u32 align(128),
322321 };
323322
324323 var a = zeroes(C_struct);
324
325 // Extern structs should have padding zeroed out.
326 try testing.expectEqualSlices(u8, &[_]u8{0} ** @sizeOf(@TypeOf(a)), asBytes(&a));
327
325328 a.y += 10;
326329
327330 try testing.expect(a.x == 0);
......@@ -402,9 +405,11 @@ test "zeroes" {
402405
403406 var c = zeroes(C_union);
404407 try testing.expectEqual(@as(u8, 0), c.a);
408 try testing.expectEqual(@as(u32, 0), c.b);
405409
406410 comptime var comptime_union = zeroes(C_union);
407411 try testing.expectEqual(@as(u8, 0), comptime_union.a);
412 try testing.expectEqual(@as(u32, 0), comptime_union.b);
408413
409414 // Ensure zero sized struct with fields is initialized correctly.
410415 _ = zeroes(struct { handle: void });