fix cast from invalid non-exhaustive enum to union

This commit is contained in:
Vexu 2020-07-27 18:42:13 +03:00
parent 1e835e0fcc
commit 2948f2d262
No known key found for this signature in database
GPG Key ID: 59AEB8936E16A6AC
2 changed files with 38 additions and 1 deletions

View File

@ -14177,7 +14177,14 @@ static IrInstGen *ir_analyze_enum_to_union(IrAnalyze *ira, IrInst* source_instr,
if (!val)
return ira->codegen->invalid_inst_gen;
TypeUnionField *union_field = find_union_field_by_tag(wanted_type, &val->data.x_enum_tag);
assert(union_field != nullptr);
if (union_field == nullptr) {
Buf *int_buf = buf_alloc();
bigint_append_buf(int_buf, &target->value->data.x_enum_tag, 10);
ir_add_error(ira, &target->base,
buf_sprintf("no tag by value %s", buf_ptr(int_buf)));
return ira->codegen->invalid_inst_gen;
}
ZigType *field_type = resolve_union_field_type(ira->codegen, union_field);
if (field_type == nullptr)
return ira->codegen->invalid_inst_gen;
@ -14213,6 +14220,13 @@ static IrInstGen *ir_analyze_enum_to_union(IrAnalyze *ira, IrInst* source_instr,
return result;
}
if (target->value->type->data.enumeration.non_exhaustive) {
ir_add_error(ira, source_instr,
buf_sprintf("runtime cast to union '%s' from non-exhustive enum",
buf_ptr(&wanted_type->name)));
return ira->codegen->invalid_inst_gen;
}
// if the union has all fields 0 bits, we can do it
// and in fact it's a noop cast because the union value is just the enum value
if (wanted_type->data.unionation.gen_field_count == 0) {

View File

@ -51,6 +51,29 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
"tmp.zig:17:23: error: cannot adjust alignment of zero sized type 'fn(u32) anytype'",
});
cases.addTest("invalid non-exhaustive enum to union",
\\const E = enum(u8) {
\\ a,
\\ b,
\\ _,
\\};
\\const U = union(E) {
\\ a,
\\ b,
\\};
\\export fn foo() void {
\\ var e = @intToEnum(E, 15);
\\ var u: U = e;
\\}
\\export fn bar() void {
\\ const e = @intToEnum(E, 15);
\\ var u: U = e;
\\}
, &[_][]const u8{
"tmp.zig:12:16: error: runtime cast to union 'U' from non-exhustive enum",
"tmp.zig:16:16: error: no tag by value 15",
});
cases.addTest("switching with exhaustive enum has '_' prong ",
\\const E = enum{
\\ a,