stage1: Reject undefined values when taking union ptr

The code rightfully assumes the union_val object to be fully initialized.

Closes #7019
This commit is contained in:
LemonBoy 2020-11-07 23:45:54 +01:00 committed by Veikka Tuominen
parent 252924ae33
commit 129ccad434
2 changed files with 26 additions and 0 deletions

View File

@ -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) {

View File

@ -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,