Skip to content

Commit c3bc290

Browse files
committed
std.mem.zeroes: Improve handling of extern struct and extern union
`extern struct` will now be recursively initialized, same as `struct`. The only difference is that the `extern` variant is initially zeroed out to ensure its padding is also set correctly. `extern union` is still initialized to its first named member, but it is also now initially zeroed out for the padding. Fixes #17258
1 parent f4c8846 commit c3bc290

File tree

1 file changed

+16
-16
lines changed

1 file changed

+16
-16
lines changed

lib/std/mem.zig

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -246,19 +246,16 @@ pub fn zeroes(comptime T: type) T {
246246
},
247247
.Struct => |struct_info| {
248248
if (@sizeOf(T) == 0) return undefined;
249+
var structure: T = undefined;
249250
if (struct_info.layout == .Extern) {
250-
var item: T = undefined;
251-
@memset(asBytes(&item), 0);
252-
return item;
253-
} else {
254-
var structure: T = undefined;
255-
inline for (struct_info.fields) |field| {
256-
if (!field.is_comptime) {
257-
@field(structure, field.name) = zeroes(@TypeOf(@field(structure, field.name)));
258-
}
251+
@memset(asBytes(&structure), 0); // Zero out padding.
252+
}
253+
inline for (struct_info.fields) |field| {
254+
if (!field.is_comptime) {
255+
@field(structure, field.name) = zeroes(@TypeOf(@field(structure, field.name)));
259256
}
260-
return structure;
261257
}
258+
return structure;
262259
},
263260
.Pointer => |ptr_info| {
264261
switch (ptr_info.size) {
@@ -292,13 +289,16 @@ pub fn zeroes(comptime T: type) T {
292289
return @splat(zeroes(info.child));
293290
},
294291
.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));
292+
if (comptime meta.containerLayout(T) != .Extern) {
293+
@compileError("Can't set a " ++ @typeName(T) ++ " to zero.");
299294
}
300-
301-
@compileError("Can't set a " ++ @typeName(T) ++ " to zero.");
295+
// The C language specification states that (global) unions
296+
// have the first named member initialized (recursively),
297+
// and any padding is initialized to zero bits.
298+
var u: T = undefined;
299+
@memset(asBytes(&u), 0); // Zero out padding.
300+
@field(u, info.fields[0].name) = zeroes(info.fields[0].type);
301+
return u;
302302
},
303303
.ErrorUnion,
304304
.ErrorSet,

0 commit comments

Comments
 (0)