authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-07-27 18:42:13+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-08-17 20:48:22+03:00
log2948f2d262926725b4b8cb5beeb4fdba00b48336
tree8922430f910aa534a5b674573790d0849675fe04
parent1e835e0fccfd82deb31922ffdee821b0b418709f
signaturelock-open Commit is signed but in an unrecognized format.

fix cast from invalid non-exhaustive enum to union


2 files changed, 38 insertions(+), 1 deletions(-)

src/ir.cpp+15-1
......@@ -14177,7 +14177,14 @@ static IrInstGen *ir_analyze_enum_to_union(IrAnalyze *ira, IrInst* source_instr,
1417714177 if (!val)
1417814178 return ira->codegen->invalid_inst_gen;
1417914179 TypeUnionField *union_field = find_union_field_by_tag(wanted_type, &val->data.x_enum_tag);
14180 assert(union_field != nullptr);
14180 if (union_field == nullptr) {
14181 Buf *int_buf = buf_alloc();
14182 bigint_append_buf(int_buf, &target->value->data.x_enum_tag, 10);
14183
14184 ir_add_error(ira, &target->base,
14185 buf_sprintf("no tag by value %s", buf_ptr(int_buf)));
14186 return ira->codegen->invalid_inst_gen;
14187 }
1418114188 ZigType *field_type = resolve_union_field_type(ira->codegen, union_field);
1418214189 if (field_type == nullptr)
1418314190 return ira->codegen->invalid_inst_gen;
......@@ -14213,6 +14220,13 @@ static IrInstGen *ir_analyze_enum_to_union(IrAnalyze *ira, IrInst* source_instr,
1421314220 return result;
1421414221 }
1421514222
14223 if (target->value->type->data.enumeration.non_exhaustive) {
14224 ir_add_error(ira, source_instr,
14225 buf_sprintf("runtime cast to union '%s' from non-exhustive enum",
14226 buf_ptr(&wanted_type->name)));
14227 return ira->codegen->invalid_inst_gen;
14228 }
14229
1421614230 // if the union has all fields 0 bits, we can do it
1421714231 // and in fact it's a noop cast because the union value is just the enum value
1421814232 if (wanted_type->data.unionation.gen_field_count == 0) {
test/compile_errors.zig+23
......@@ -51,6 +51,29 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
5151 "tmp.zig:17:23: error: cannot adjust alignment of zero sized type 'fn(u32) anytype'",
5252 });
5353
54 cases.addTest("invalid non-exhaustive enum to union",
55 \\const E = enum(u8) {
56 \\ a,
57 \\ b,
58 \\ _,
59 \\};
60 \\const U = union(E) {
61 \\ a,
62 \\ b,
63 \\};
64 \\export fn foo() void {
65 \\ var e = @intToEnum(E, 15);
66 \\ var u: U = e;
67 \\}
68 \\export fn bar() void {
69 \\ const e = @intToEnum(E, 15);
70 \\ var u: U = e;
71 \\}
72 , &[_][]const u8{
73 "tmp.zig:12:16: error: runtime cast to union 'U' from non-exhustive enum",
74 "tmp.zig:16:16: error: no tag by value 15",
75 });
76
5477 cases.addTest("switching with exhaustive enum has '_' prong ",
5578 \\const E = enum{
5679 \\ a,