Commit 129ccad434
Changed files (2)
src
stage1
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<ZigValue>();
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) {
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,