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,...@@ -14177,7 +14177,14 @@ static IrInstGen *ir_analyze_enum_to_union(IrAnalyze *ira, IrInst* source_instr,
14177 if (!val)14177 if (!val)
14178 return ira->codegen->invalid_inst_gen;14178 return ira->codegen->invalid_inst_gen;
14179 TypeUnionField *union_field = find_union_field_by_tag(wanted_type, &val->data.x_enum_tag);14179 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 }
14181 ZigType *field_type = resolve_union_field_type(ira->codegen, union_field);14188 ZigType *field_type = resolve_union_field_type(ira->codegen, union_field);
14182 if (field_type == nullptr)14189 if (field_type == nullptr)
14183 return ira->codegen->invalid_inst_gen;14190 return ira->codegen->invalid_inst_gen;
...@@ -14213,6 +14220,13 @@ static IrInstGen *ir_analyze_enum_to_union(IrAnalyze *ira, IrInst* source_instr,...@@ -14213,6 +14220,13 @@ static IrInstGen *ir_analyze_enum_to_union(IrAnalyze *ira, IrInst* source_instr,
14213 return result;14220 return result;
14214 }14221 }
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
14216 // if the union has all fields 0 bits, we can do it14230 // if the union has all fields 0 bits, we can do it
14217 // and in fact it's a noop cast because the union value is just the enum value14231 // and in fact it's a noop cast because the union value is just the enum value
14218 if (wanted_type->data.unionation.gen_field_count == 0) {14232 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 {...@@ -51,6 +51,29 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
51 "tmp.zig:17:23: error: cannot adjust alignment of zero sized type 'fn(u32) anytype'",51 "tmp.zig:17:23: error: cannot adjust alignment of zero sized type 'fn(u32) anytype'",
52 });52 });
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
54 cases.addTest("switching with exhaustive enum has '_' prong ",77 cases.addTest("switching with exhaustive enum has '_' prong ",
55 \\const E = enum{78 \\const E = enum{
56 \\ a,79 \\ a,