| author | |
| committer | |
| log | dcc406deff0fb4ee3c2cd1f4ff8614e972a8ea7a |
| tree | ce198a2b6005c96a74a65de3b7af7126efc7be23 |
| parent | e60be3082499ff19078699675044b993f6921ad0 |
* Adds error message for types: enum, int and bool
* Adds compile error tests2 files changed, 113 insertions(+), 3 deletions(-)
src/ir.cpp+17-3| ... | @@ -28700,6 +28700,10 @@ static IrInstGen *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira, | ... | @@ -28700,6 +28700,10 @@ static IrInstGen *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira, |
| 28700 | buf_ptr(enum_field->name))); | 28700 | buf_ptr(enum_field->name))); |
| 28701 | } | 28701 | } |
| 28702 | } | 28702 | } |
| 28703 | } else if(!switch_type->data.enumeration.non_exhaustive && switch_type->data.enumeration.src_field_count == instruction->range_count) { | ||
| 28704 | ir_add_error_node(ira, instruction->else_prong, | ||
| 28705 | buf_sprintf("unreachable else prong, all cases already handled")); | ||
| 28706 | return ira->codegen->invalid_inst_gen; | ||
| 28703 | } | 28707 | } |
| 28704 | } else if (switch_type->id == ZigTypeIdErrorSet) { | 28708 | } else if (switch_type->id == ZigTypeIdErrorSet) { |
| 28705 | if (!resolve_inferred_error_set(ira->codegen, switch_type, target_value->base.source_node)) { | 28709 | if (!resolve_inferred_error_set(ira->codegen, switch_type, target_value->base.source_node)) { |
| ... | @@ -28808,16 +28812,20 @@ static IrInstGen *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira, | ... | @@ -28808,16 +28812,20 @@ static IrInstGen *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira, |
| 28808 | return ira->codegen->invalid_inst_gen; | 28812 | return ira->codegen->invalid_inst_gen; |
| 28809 | } | 28813 | } |
| 28810 | } | 28814 | } |
| 28811 | if (instruction->else_prong == nullptr) { | 28815 | |
| 28812 | BigInt min_val; | 28816 | BigInt min_val; |
| 28813 | eval_min_max_value_int(ira->codegen, switch_type, &min_val, false); | 28817 | eval_min_max_value_int(ira->codegen, switch_type, &min_val, false); |
| 28814 | BigInt max_val; | 28818 | BigInt max_val; |
| 28815 | eval_min_max_value_int(ira->codegen, switch_type, &max_val, true); | 28819 | eval_min_max_value_int(ira->codegen, switch_type, &max_val, true); |
| 28816 | if (!rangeset_spans(&rs, &min_val, &max_val)) { | 28820 | bool handles_all_cases = rangeset_spans(&rs, &min_val, &max_val); |
| 28821 | if (!handles_all_cases && instruction->else_prong == nullptr) { | ||
| 28817 | ir_add_error(ira, &instruction->base.base, buf_sprintf("switch must handle all possibilities")); | 28822 | ir_add_error(ira, &instruction->base.base, buf_sprintf("switch must handle all possibilities")); |
| 28818 | return ira->codegen->invalid_inst_gen; | 28823 | return ira->codegen->invalid_inst_gen; |
| 28824 | } else if(handles_all_cases && instruction->else_prong != nullptr) { | ||
| 28825 | ir_add_error_node(ira, instruction->else_prong, | ||
| 28826 | buf_sprintf("unreachable else prong, all cases already handled")); | ||
| 28827 | return ira->codegen->invalid_inst_gen; | ||
| 28819 | } | 28828 | } |
| 28820 | } | ||
| 28821 | } else if (switch_type->id == ZigTypeIdBool) { | 28829 | } else if (switch_type->id == ZigTypeIdBool) { |
| 28822 | int seenTrue = 0; | 28830 | int seenTrue = 0; |
| 28823 | int seenFalse = 0; | 28831 | int seenFalse = 0; |
| ... | @@ -28851,6 +28859,12 @@ static IrInstGen *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira, | ... | @@ -28851,6 +28859,12 @@ static IrInstGen *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira, |
| 28851 | ir_add_error(ira, &instruction->base.base, buf_sprintf("switch must handle all possibilities")); | 28859 | ir_add_error(ira, &instruction->base.base, buf_sprintf("switch must handle all possibilities")); |
| 28852 | return ira->codegen->invalid_inst_gen; | 28860 | return ira->codegen->invalid_inst_gen; |
| 28853 | } | 28861 | } |
| 28862 | |||
| 28863 | if(seenTrue == 1 && seenFalse == 1 && instruction->else_prong != nullptr) { | ||
| 28864 | ir_add_error_node(ira, instruction->else_prong, | ||
| 28865 | buf_sprintf("unreachable else prong, all cases already handled")); | ||
| 28866 | return ira->codegen->invalid_inst_gen; | ||
| 28867 | } | ||
| 28854 | } else if (instruction->else_prong == nullptr) { | 28868 | } else if (instruction->else_prong == nullptr) { |
| 28855 | ir_add_error(ira, &instruction->base.base, | 28869 | ir_add_error(ira, &instruction->base.base, |
| 28856 | buf_sprintf("else prong required when switching on type '%s'", buf_ptr(&switch_type->name))); | 28870 | buf_sprintf("else prong required when switching on type '%s'", buf_ptr(&switch_type->name))); |
test/compile_errors.zig+96| ... | @@ -468,6 +468,102 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -468,6 +468,102 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 468 | "tmp.zig:12:5: error: switch on non-exhaustive enum must include `else` or `_` prong", | 468 | "tmp.zig:12:5: error: switch on non-exhaustive enum must include `else` or `_` prong", |
| 469 | }); | 469 | }); |
| 470 | 470 | ||
| 471 | cases.add("switch expression - unreachable else prong (bool)", | ||
| 472 | \\fn foo(x: bool) void { | ||
| 473 | \\ switch (x) { | ||
| 474 | \\ true => {}, | ||
| 475 | \\ false => {}, | ||
| 476 | \\ else => {}, | ||
| 477 | \\ } | ||
| 478 | \\} | ||
| 479 | \\export fn entry() usize { return @sizeOf(@TypeOf(foo)); } | ||
| 480 | , &[_][]const u8{ | ||
| 481 | "tmp.zig:5:9: error: unreachable else prong, all cases already handled", | ||
| 482 | }); | ||
| 483 | |||
| 484 | cases.add("switch expression - unreachable else prong (u1)", | ||
| 485 | \\fn foo(x: u1) void { | ||
| 486 | \\ switch (x) { | ||
| 487 | \\ 0 => {}, | ||
| 488 | \\ 1 => {}, | ||
| 489 | \\ else => {}, | ||
| 490 | \\ } | ||
| 491 | \\} | ||
| 492 | \\export fn entry() usize { return @sizeOf(@TypeOf(foo)); } | ||
| 493 | , &[_][]const u8{ | ||
| 494 | "tmp.zig:5:9: error: unreachable else prong, all cases already handled", | ||
| 495 | }); | ||
| 496 | |||
| 497 | cases.add("switch expression - unreachable else prong (u2)", | ||
| 498 | \\fn foo(x: u2) void { | ||
| 499 | \\ switch (x) { | ||
| 500 | \\ 0 => {}, | ||
| 501 | \\ 1 => {}, | ||
| 502 | \\ 2 => {}, | ||
| 503 | \\ 3 => {}, | ||
| 504 | \\ else => {}, | ||
| 505 | \\ } | ||
| 506 | \\} | ||
| 507 | \\export fn entry() usize { return @sizeOf(@TypeOf(foo)); } | ||
| 508 | , &[_][]const u8{ | ||
| 509 | "tmp.zig:7:9: error: unreachable else prong, all cases already handled", | ||
| 510 | }); | ||
| 511 | |||
| 512 | cases.add("switch expression - unreachable else prong (range u8)", | ||
| 513 | \\fn foo(x: u8) void { | ||
| 514 | \\ switch (x) { | ||
| 515 | \\ 0 => {}, | ||
| 516 | \\ 1 => {}, | ||
| 517 | \\ 2 => {}, | ||
| 518 | \\ 3 => {}, | ||
| 519 | \\ 4...255 => {}, | ||
| 520 | \\ else => {}, | ||
| 521 | \\ } | ||
| 522 | \\} | ||
| 523 | \\export fn entry() usize { return @sizeOf(@TypeOf(foo)); } | ||
| 524 | , &[_][]const u8{ | ||
| 525 | "tmp.zig:8:9: error: unreachable else prong, all cases already handled", | ||
| 526 | }); | ||
| 527 | |||
| 528 | cases.add("switch expression - unreachable else prong (range i8)", | ||
| 529 | \\fn foo(x: i8) void { | ||
| 530 | \\ switch (x) { | ||
| 531 | \\ -128...0 => {}, | ||
| 532 | \\ 1 => {}, | ||
| 533 | \\ 2 => {}, | ||
| 534 | \\ 3 => {}, | ||
| 535 | \\ 4...127 => {}, | ||
| 536 | \\ else => {}, | ||
| 537 | \\ } | ||
| 538 | \\} | ||
| 539 | \\export fn entry() usize { return @sizeOf(@TypeOf(foo)); } | ||
| 540 | , &[_][]const u8{ | ||
| 541 | "tmp.zig:8:9: error: unreachable else prong, all cases already handled", | ||
| 542 | }); | ||
| 543 | |||
| 544 | cases.add("switch expression - unreachable else prong (enum)", | ||
| 545 | \\const TestEnum = enum{ T1, T2 }; | ||
| 546 | \\ | ||
| 547 | \\fn err(x: u8) TestEnum { | ||
| 548 | \\ switch (x) { | ||
| 549 | \\ 0 => return TestEnum.T1, | ||
| 550 | \\ else => return TestEnum.T2, | ||
| 551 | \\ } | ||
| 552 | \\} | ||
| 553 | \\ | ||
| 554 | \\fn foo(x: u8) void { | ||
| 555 | \\ switch (err(x)) { | ||
| 556 | \\ TestEnum.T1 => {}, | ||
| 557 | \\ TestEnum.T2 => {}, | ||
| 558 | \\ else => {}, | ||
| 559 | \\ } | ||
| 560 | \\} | ||
| 561 | \\ | ||
| 562 | \\export fn entry() usize { return @sizeOf(@TypeOf(foo)); } | ||
| 563 | , &[_][]const u8{ | ||
| 564 | "tmp.zig:14:9: error: unreachable else prong, all cases already handled", | ||
| 565 | }); | ||
| 566 | |||
| 471 | cases.addTest("@export with empty name string", | 567 | cases.addTest("@export with empty name string", |
| 472 | \\pub export fn entry() void { } | 568 | \\pub export fn entry() void { } |
| 473 | \\comptime { | 569 | \\comptime { |