From ba5cbea0c3c6ee2e22606365edde18342fcf0579 Mon Sep 17 00:00:00 2001 From: kkHAIKE Date: Tue, 27 Sep 2022 18:23:51 +0800 Subject: [PATCH] Sema: fix segfault when union init with empty field --- src/Sema.zig | 13 +++++-- ...nion_init_with_none_or_multiple_fields.zig | 37 +++++++++++++++++++ 2 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 test/cases/compile_errors/union_init_with_none_or_multiple_fields.zig diff --git a/src/Sema.zig b/src/Sema.zig index 72a5cb518f..ad3bd355eb 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -15885,6 +15885,7 @@ fn zirStructInitEmpty(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE .Struct => return sema.structInitEmpty(block, obj_ty, src, src), .Array, .Vector => return sema.arrayInitEmpty(block, src, obj_ty), .Void => return sema.addConstant(obj_ty, Value.void), + .Union => return sema.fail(block, src, "union initializer must initialize one field", .{}), else => return sema.failWithArrayInitNotSupported(block, src, obj_ty), } } @@ -25854,14 +25855,19 @@ fn coerceAnonStructToUnion( inst_src: LazySrcLoc, ) !Air.Inst.Ref { const inst_ty = sema.typeOf(inst); - const anon_struct = inst_ty.castTag(.anon_struct).?.data; - if (anon_struct.types.len != 1) { + const field_count = inst_ty.structFieldCount(); + if (field_count != 1) { const msg = msg: { - const msg = try sema.errMsg( + const msg = if (field_count > 1) try sema.errMsg( block, inst_src, "cannot initialize multiple union fields at once, unions can only have one active field", .{}, + ) else try sema.errMsg( + block, + inst_src, + "union initializer must initialize one field", + .{}, ); errdefer msg.destroy(sema.gpa); @@ -25874,6 +25880,7 @@ fn coerceAnonStructToUnion( return sema.failWithOwnedErrorMsg(msg); } + const anon_struct = inst_ty.castTag(.anon_struct).?.data; const field_name = anon_struct.names[0]; const init = try sema.structFieldVal(block, inst_src, inst, field_name, inst_src, inst_ty); return sema.unionInit(block, init, inst_src, union_ty, union_ty_src, field_name, inst_src); diff --git a/test/cases/compile_errors/union_init_with_none_or_multiple_fields.zig b/test/cases/compile_errors/union_init_with_none_or_multiple_fields.zig new file mode 100644 index 0000000000..5f486bf2b7 --- /dev/null +++ b/test/cases/compile_errors/union_init_with_none_or_multiple_fields.zig @@ -0,0 +1,37 @@ +const U1 = union { + a: u8, + b: i8, +}; +const U2 = union(enum) { + a: u8, + b: i8, +}; +export fn u1z() void { + const x: U1 = .{}; + _ = x; +} +export fn u1m() void { + const x: U1 = .{ .a = 1, .b = 1 }; + _ = x; +} +export fn u2z() void { + const x: U2 = U2{}; + _ = x; +} +export fn u2m() void { + const x: U2 = .{ .a = 1, .b = 1 }; + _ = x; +} + +// error +// backend=stage2 +// target=native +// +// :9:1: error: union initializer must initialize one field +// :14:20: error: cannot initialize multiple union fields at once, unions can only have one active field +// :14:31: note: additional initializer here +// :18:21: error: union initializer must initialize one field +// :22:20: error: cannot initialize multiple union fields at once, unions can only have one active field +// :22:31: note: additional initializer here +// :1:12: note: union declared here +// :5:12: note: union declared here