| author | |
| committer | |
| log | 0f38410ea6f60ce9cebf373069d4abfcac0e77e6 |
| tree | a57673939888845bd3eb1553da5d6a23342e0e7f |
| parent | 59de23dfa010c5556f79fbb8b4c637c8d150fd88 |
| signature | Commit is signed but in an unrecognized format. |
7 files changed, 57 insertions(+), 3 deletions(-)
src-self-hosted/translate_c.zig+3| ... | @@ -282,6 +282,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void { | ... | @@ -282,6 +282,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void { |
| 282 | .PrivateExtern => return failDecl(c, fn_decl_loc, fn_name, "unsupported storage class: private extern", .{}), | 282 | .PrivateExtern => return failDecl(c, fn_decl_loc, fn_name, "unsupported storage class: private extern", .{}), |
| 283 | .Auto => unreachable, // Not legal on functions | 283 | .Auto => unreachable, // Not legal on functions |
| 284 | .Register => unreachable, // Not legal on functions | 284 | .Register => unreachable, // Not legal on functions |
| 285 | else => unreachable, | ||
| 285 | }, | 286 | }, |
| 286 | }; | 287 | }; |
| 287 | const proto_node = switch (ZigClangType_getTypeClass(fn_type)) { | 288 | const proto_node = switch (ZigClangType_getTypeClass(fn_type)) { |
| ... | @@ -710,6 +711,7 @@ fn transBinaryOperator( | ... | @@ -710,6 +711,7 @@ fn transBinaryOperator( |
| 710 | .XorAssign, | 711 | .XorAssign, |
| 711 | .OrAssign, | 712 | .OrAssign, |
| 712 | => unreachable, | 713 | => unreachable, |
| 714 | else => unreachable, | ||
| 713 | } | 715 | } |
| 714 | } | 716 | } |
| 715 | 717 | ||
| ... | @@ -1001,6 +1003,7 @@ fn transStringLiteral( | ... | @@ -1001,6 +1003,7 @@ fn transStringLiteral( |
| 1001 | "TODO: support string literal kind {}", | 1003 | "TODO: support string literal kind {}", |
| 1002 | .{kind}, | 1004 | .{kind}, |
| 1003 | ), | 1005 | ), |
| 1006 | else => unreachable, | ||
| 1004 | } | 1007 | } |
| 1005 | } | 1008 | } |
| 1006 | 1009 |
src/analyze.cpp+1-1| ... | @@ -2682,7 +2682,7 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { | ... | @@ -2682,7 +2682,7 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { |
| 2682 | 2682 | ||
| 2683 | // Make sure the value is unique | 2683 | // Make sure the value is unique |
| 2684 | auto entry = occupied_tag_values.put_unique(type_enum_field->value, field_node); | 2684 | auto entry = occupied_tag_values.put_unique(type_enum_field->value, field_node); |
| 2685 | if (entry != nullptr) { | 2685 | if (entry != nullptr && enum_type->data.enumeration.layout != ContainerLayoutExtern) { |
| 2686 | enum_type->data.enumeration.resolve_status = ResolveStatusInvalid; | 2686 | enum_type->data.enumeration.resolve_status = ResolveStatusInvalid; |
| 2687 | 2687 | ||
| 2688 | Buf *val_buf = buf_alloc(); | 2688 | Buf *val_buf = buf_alloc(); |
src/codegen.cpp+1-1| ... | @@ -3292,7 +3292,7 @@ static LLVMValueRef ir_render_int_to_enum(CodeGen *g, IrExecutable *executable, | ... | @@ -3292,7 +3292,7 @@ static LLVMValueRef ir_render_int_to_enum(CodeGen *g, IrExecutable *executable, |
| 3292 | LLVMValueRef tag_int_value = gen_widen_or_shorten(g, ir_want_runtime_safety(g, &instruction->base), | 3292 | LLVMValueRef tag_int_value = gen_widen_or_shorten(g, ir_want_runtime_safety(g, &instruction->base), |
| 3293 | instruction->target->value->type, tag_int_type, target_val); | 3293 | instruction->target->value->type, tag_int_type, target_val); |
| 3294 | 3294 | ||
| 3295 | if (ir_want_runtime_safety(g, &instruction->base)) { | 3295 | if (ir_want_runtime_safety(g, &instruction->base) && wanted_type->data.enumeration.layout != ContainerLayoutExtern) { |
| 3296 | LLVMBasicBlockRef bad_value_block = LLVMAppendBasicBlock(g->cur_fn_val, "BadValue"); | 3296 | LLVMBasicBlockRef bad_value_block = LLVMAppendBasicBlock(g->cur_fn_val, "BadValue"); |
| 3297 | LLVMBasicBlockRef ok_value_block = LLVMAppendBasicBlock(g->cur_fn_val, "OkValue"); | 3297 | LLVMBasicBlockRef ok_value_block = LLVMAppendBasicBlock(g->cur_fn_val, "OkValue"); |
| 3298 | size_t field_count = wanted_type->data.enumeration.src_field_count; | 3298 | size_t field_count = wanted_type->data.enumeration.src_field_count; |
src/ir.cpp+5-1| ... | @@ -12728,7 +12728,7 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour | ... | @@ -12728,7 +12728,7 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour |
| 12728 | return ira->codegen->invalid_instruction; | 12728 | return ira->codegen->invalid_instruction; |
| 12729 | 12729 | ||
| 12730 | TypeEnumField *field = find_enum_field_by_tag(wanted_type, &val->data.x_bigint); | 12730 | TypeEnumField *field = find_enum_field_by_tag(wanted_type, &val->data.x_bigint); |
| 12731 | if (field == nullptr) { | 12731 | if (field == nullptr && wanted_type->data.enumeration.layout != ContainerLayoutExtern) { |
| 12732 | Buf *val_buf = buf_alloc(); | 12732 | Buf *val_buf = buf_alloc(); |
| 12733 | bigint_append_buf(val_buf, &val->data.x_bigint, 10); | 12733 | bigint_append_buf(val_buf, &val->data.x_bigint, 10); |
| 12734 | ErrorMsg *msg = ir_add_error(ira, source_instr, | 12734 | ErrorMsg *msg = ir_add_error(ira, source_instr, |
| ... | @@ -25791,6 +25791,10 @@ static IrInstruction *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira, | ... | @@ -25791,6 +25791,10 @@ static IrInstruction *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira, |
| 25791 | } | 25791 | } |
| 25792 | } | 25792 | } |
| 25793 | if (!instruction->have_else_prong) { | 25793 | if (!instruction->have_else_prong) { |
| 25794 | if (switch_type->data.enumeration.layout == ContainerLayoutExtern) { | ||
| 25795 | ir_add_error(ira, &instruction->base, | ||
| 25796 | buf_sprintf("switch on an extern enum must have an else prong")); | ||
| 25797 | } | ||
| 25794 | for (uint32_t i = 0; i < switch_type->data.enumeration.src_field_count; i += 1) { | 25798 | for (uint32_t i = 0; i < switch_type->data.enumeration.src_field_count; i += 1) { |
| 25795 | TypeEnumField *enum_field = &switch_type->data.enumeration.fields[i]; | 25799 | TypeEnumField *enum_field = &switch_type->data.enumeration.fields[i]; |
| 25796 | 25800 |
test/compile_errors.zig+19| ... | @@ -10,6 +10,25 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -10,6 +10,25 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 10 | "tmp.zig:2:13: error: pointer type '[*]align(4) u8' requires aligned address", | 10 | "tmp.zig:2:13: error: pointer type '[*]align(4) u8' requires aligned address", |
| 11 | }); | 11 | }); |
| 12 | 12 | ||
| 13 | cases.add("switch on extern enum missing else prong", | ||
| 14 | \\const i = extern enum { | ||
| 15 | \\ n = 0, | ||
| 16 | \\ o = 2, | ||
| 17 | \\ p = 4, | ||
| 18 | \\ q = 4, | ||
| 19 | \\}; | ||
| 20 | \\pub fn main() void { | ||
| 21 | \\ var x = @intToEnum(i, 52); | ||
| 22 | \\ switch (x) { | ||
| 23 | \\ .n, | ||
| 24 | \\ .o, | ||
| 25 | \\ .p => unreachable, | ||
| 26 | \\ } | ||
| 27 | \\} | ||
| 28 | , &[_][]const u8{ | ||
| 29 | "tmp.zig:9:5: error: switch on an extern enum must have an else prong", | ||
| 30 | }); | ||
| 31 | |||
| 13 | cases.add("invalid float literal", | 32 | cases.add("invalid float literal", |
| 14 | \\const std = @import("std"); | 33 | \\const std = @import("std"); |
| 15 | \\ | 34 | \\ |
test/stage1/behavior/cast.zig+1| ... | @@ -618,6 +618,7 @@ test "peer resolution of string literals" { | ... | @@ -618,6 +618,7 @@ test "peer resolution of string literals" { |
| 618 | .b => "two", | 618 | .b => "two", |
| 619 | .c => "three", | 619 | .c => "three", |
| 620 | .d => "four", | 620 | .d => "four", |
| 621 | else => unreachable, | ||
| 621 | }; | 622 | }; |
| 622 | expect(mem.eql(u8, cmd, "two")); | 623 | expect(mem.eql(u8, cmd, "two")); |
| 623 | } | 624 | } |
test/stage1/behavior/enum.zig+27| ... | @@ -1,6 +1,33 @@ | ... | @@ -1,6 +1,33 @@ |
| 1 | const expect = @import("std").testing.expect; | 1 | const expect = @import("std").testing.expect; |
| 2 | const mem = @import("std").mem; | 2 | const mem = @import("std").mem; |
| 3 | 3 | ||
| 4 | test "extern enum" { | ||
| 5 | const S = struct { | ||
| 6 | const i = extern enum { | ||
| 7 | n = 0, | ||
| 8 | o = 2, | ||
| 9 | p = 4, | ||
| 10 | q = 4, | ||
| 11 | }; | ||
| 12 | fn doTheTest(y: c_int) void { | ||
| 13 | var x = i.o; | ||
| 14 | expect(@enumToInt(x) == 2); | ||
| 15 | x = @intToEnum(i, 12); | ||
| 16 | expect(@enumToInt(x) == 12); | ||
| 17 | x = @intToEnum(i, y); | ||
| 18 | expect(@enumToInt(x) == 52); | ||
| 19 | switch (x) { | ||
| 20 | .n, | ||
| 21 | .o, | ||
| 22 | .p => unreachable, | ||
| 23 | else => {}, | ||
| 24 | } | ||
| 25 | } | ||
| 26 | }; | ||
| 27 | S.doTheTest(52); | ||
| 28 | comptime S.doTheTest(52); | ||
| 29 | } | ||
| 30 | |||
| 4 | test "enum type" { | 31 | test "enum type" { |
| 5 | const foo1 = Foo{ .One = 13 }; | 32 | const foo1 = Foo{ .One = 13 }; |
| 6 | const foo2 = Foo{ | 33 | const foo2 = Foo{ |