zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 00ff123b1eb237f72f918ffd413c8d9c8936c46d (tree)
parent 8bd94759bf48c3247d4de14806ff2f510cb36591
Author: John Schmidt <john.schmidt.h@gmail.com>
Date:   Mon, 19 Feb 2024 13:46:52 +0100

Sema: fix compile error for switching on undefined union

Before this fix, passing an undefined union value to `Sema.switchCond`
returned an undefined value of the union type, not the tag type, since
`Value.unionTag` forwards undefined values unchanged.
This leads us into the `.Union` branch in `Sema.zirSwitchBlock` which is
unreachable, now we take the `.Enum` branch instead.

Diffstat:
Msrc/Sema.zig | 7+++++--
Atest/cases/compile_errors/switch_on_undefined_union.zig | 12++++++++++++
2 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/src/Sema.zig b/src/Sema.zig @@ -11658,7 +11658,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r // Validate for duplicate items, missing else prong, and invalid range. switch (operand_ty.zigTypeTag(mod)) { - .Union => unreachable, // handled in zirSwitchCond + .Union => unreachable, // handled in `switchCond` .Enum => { seen_enum_fields = try gpa.alloc(?Module.SwitchProngSrc, operand_ty.enumFieldCount(mod)); empty_enum = seen_enum_fields.len == 0 and !operand_ty.isNonexhaustiveEnum(mod); @@ -33747,7 +33747,10 @@ fn unionToTag( return Air.internedToRef(opv.toIntern()); } if (try sema.resolveValue(un)) |un_val| { - return Air.internedToRef(un_val.unionTag(mod).?.toIntern()); + const tag_val = un_val.unionTag(mod).?; + if (tag_val.isUndef(mod)) + return try mod.undefRef(enum_ty); + return Air.internedToRef(tag_val.toIntern()); } try sema.requireRuntimeBlock(block, un_src, null); return block.addTyOp(.get_union_tag, enum_ty, un); diff --git a/test/cases/compile_errors/switch_on_undefined_union.zig b/test/cases/compile_errors/switch_on_undefined_union.zig @@ -0,0 +1,12 @@ +export fn entry() void { + const U = union(enum) { a: bool, b: bool }; + switch (@as(U, undefined)) { + .a, .b => {}, + } +} + +// error +// backend=stage2 +// target=native +// +// :3:5: error: use of undefined value here causes undefined behavior