| author | |
| committer | |
| log | 78840c4ab20d844ca866fa0ab437d72fdec62d0d |
| tree | afd5ee223f3c9ec0a13b9fa621d43c62e66bf9f5 |
| parent | f85d7199521290121ade4506ea53acdaf6284982 |
The T type should be wide enough to fit values in the 0...num field
range.
Closes #69882 files changed, 47 insertions(+), 0 deletions(-)
src/stage1/analyze.cpp+16| ... | @@ -3178,6 +3178,22 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) { | ... | @@ -3178,6 +3178,22 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) { |
| 3178 | union_type->data.unionation.resolve_status = ResolveStatusInvalid; | 3178 | union_type->data.unionation.resolve_status = ResolveStatusInvalid; |
| 3179 | return ErrorSemanticAnalyzeFail; | 3179 | return ErrorSemanticAnalyzeFail; |
| 3180 | } | 3180 | } |
| 3181 | if (tag_int_type->id == ZigTypeIdInt) { | ||
| 3182 | BigInt bi; | ||
| 3183 | bigint_init_unsigned(&bi, field_count - 1); | ||
| 3184 | if (!bigint_fits_in_bits(&bi, | ||
| 3185 | tag_int_type->data.integral.bit_count, | ||
| 3186 | tag_int_type->data.integral.is_signed)) | ||
| 3187 | { | ||
| 3188 | ErrorMsg *msg = add_node_error(g, enum_type_node, | ||
| 3189 | buf_sprintf("specified integer tag type cannot represent every field")); | ||
| 3190 | add_error_note(g, msg, enum_type_node, | ||
| 3191 | buf_sprintf("type %s cannot fit values in range 0...%" PRIu32, | ||
| 3192 | buf_ptr(&tag_int_type->name), field_count - 1)); | ||
| 3193 | union_type->data.unionation.resolve_status = ResolveStatusInvalid; | ||
| 3194 | return ErrorSemanticAnalyzeFail; | ||
| 3195 | } | ||
| 3196 | } | ||
| 3181 | } else { | 3197 | } else { |
| 3182 | tag_int_type = get_smallest_unsigned_int_type(g, field_count - 1); | 3198 | tag_int_type = get_smallest_unsigned_int_type(g, field_count - 1); |
| 3183 | } | 3199 | } |
test/compile_errors.zig+31| ... | @@ -2,6 +2,37 @@ const tests = @import("tests.zig"); | ... | @@ -2,6 +2,37 @@ const tests = @import("tests.zig"); |
| 2 | const std = @import("std"); | 2 | const std = @import("std"); |
| 3 | 3 | ||
| 4 | pub fn addCases(cases: *tests.CompileErrorContext) void { | 4 | pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 5 | cases.add("union with too small explicit signed tag type", | ||
| 6 | \\const U = union(enum(i2)) { | ||
| 7 | \\ A: u8, | ||
| 8 | \\ B: u8, | ||
| 9 | \\ C: u8, | ||
| 10 | \\ D: u8, | ||
| 11 | \\}; | ||
| 12 | \\export fn entry() void { | ||
| 13 | \\ _ = U{ .D = 1 }; | ||
| 14 | \\} | ||
| 15 | , &[_][]const u8{ | ||
| 16 | "tmp.zig:1:22: error: specified integer tag type cannot represent every field", | ||
| 17 | "tmp.zig:1:22: note: type i2 cannot fit values in range 0...3", | ||
| 18 | }); | ||
| 19 | |||
| 20 | cases.add("union with too small explicit unsigned tag type", | ||
| 21 | \\const U = union(enum(u2)) { | ||
| 22 | \\ A: u8, | ||
| 23 | \\ B: u8, | ||
| 24 | \\ C: u8, | ||
| 25 | \\ D: u8, | ||
| 26 | \\ E: u8, | ||
| 27 | \\}; | ||
| 28 | \\export fn entry() void { | ||
| 29 | \\ _ = U{ .E = 1 }; | ||
| 30 | \\} | ||
| 31 | , &[_][]const u8{ | ||
| 32 | "tmp.zig:1:22: error: specified integer tag type cannot represent every field", | ||
| 33 | "tmp.zig:1:22: note: type u2 cannot fit values in range 0...4", | ||
| 34 | }); | ||
| 35 | |||
| 5 | cases.add("unreachable executed at comptime", | 36 | cases.add("unreachable executed at comptime", |
| 6 | \\fn foo(comptime x: i32) i32 { | 37 | \\fn foo(comptime x: i32) i32 { |
| 7 | \\ comptime { | 38 | \\ comptime { |