@@ -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 (field .type );
259256 }
260- return structure ;
261257 }
258+ return structure ;
262259 },
263260 .Pointer = > | ptr_info | {
264261 switch (ptr_info .size ) {
@@ -292,13 +289,17 @@ 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 (info .layout != .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+ const field = info .fields [0 ];
299+ var u = @unionInit (T , field .name , zeroes (field .type ));
300+ const padding = asBytes (& u )[@sizeOf (field .type ).. ];
301+ if (padding .len > 0 ) @memset (padding , 0 );
302+ return u ;
302303 },
303304 .ErrorUnion ,
304305 .ErrorSet ,
@@ -318,10 +319,14 @@ pub fn zeroes(comptime T: type) T {
318319test "zeroes" {
319320 const C_struct = extern struct {
320321 x : u32 ,
321- y : u32 ,
322+ y : u32 align ( 128 ) ,
322323 };
323324
324325 var a = zeroes (C_struct );
326+
327+ // Extern structs should have padding zeroed out.
328+ try testing .expectEqualSlices (u8 , &[_ ]u8 {0 } ** @sizeOf (@TypeOf (a )), asBytes (& a ));
329+
325330 a .y += 10 ;
326331
327332 try testing .expect (a .x == 0 );
@@ -402,9 +407,11 @@ test "zeroes" {
402407
403408 var c = zeroes (C_union );
404409 try testing .expectEqual (@as (u8 , 0 ), c .a );
410+ try testing .expectEqual (@as (u32 , 0 ), c .b );
405411
406412 comptime var comptime_union = zeroes (C_union );
407413 try testing .expectEqual (@as (u8 , 0 ), comptime_union .a );
414+ try testing .expectEqual (@as (u32 , 0 ), comptime_union .b );
408415
409416 // Ensure zero sized struct with fields is initialized correctly.
410417 _ = zeroes (struct { handle : void });
0 commit comments