diff --git a/src/stage1/ir.cpp b/src/stage1/ir.cpp index a513bd6ee8..1be9507480 100644 --- a/src/stage1/ir.cpp +++ b/src/stage1/ir.cpp @@ -22713,6 +22713,16 @@ static IrInstGen *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name if (type_is_invalid(union_val->type)) return ira->codegen->invalid_inst_gen; + // Reject undefined values unless we're intializing the union: + // a undefined union means also the tag is undefined, accessing + // its payload slot is UB. + const UndefAllowed allow_undef = initializing ? UndefOk : UndefBad; + if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec, + source_instr->source_node, union_val, allow_undef))) + { + return ira->codegen->invalid_inst_gen; + } + if (initializing) { ZigValue *payload_val = ira->codegen->pass1_arena->create(); payload_val->special = ConstValSpecialUndef; @@ -22737,6 +22747,7 @@ static IrInstGen *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name } ZigValue *payload_val = union_val->data.x_union.payload; + assert(payload_val); IrInstGen *result; if (ptr_val->data.x_ptr.mut == ConstPtrMutInfer) { diff --git a/test/compile_errors.zig b/test/compile_errors.zig index f81458ae8b..1d16cd6706 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -11,6 +11,21 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { "tmp.zig:1:50: error: use of undefined value here causes undefined behavior", }); + cases.add("wrong initializer for union payload of type 'type'", + \\const U = union(enum) { + \\ A: type, + \\}; + \\const S = struct { + \\ u: U, + \\}; + \\export fn entry() void { + \\ comptime var v: S = undefined; + \\ v.u.A = U{ .A = i32 }; + \\} + , &[_][]const u8{ + "tmp.zig:9:8: error: use of undefined value here causes undefined behavior", + }); + cases.add("union with too small explicit signed tag type", \\const U = union(enum(i2)) { \\ A: u8,