authorgravatar for liljaanton2001@gmail.comantlilja <liljaanton2001@gmail.com> 2020-06-24 19:12:42+02:00
committergravatar for liljaanton2001@gmail.comantlilja <liljaanton2001@gmail.com> 2020-07-01 16:09:36+02:00
logdcc406deff0fb4ee3c2cd1f4ff8614e972a8ea7a
treece198a2b6005c96a74a65de3b7af7126efc7be23
parente60be3082499ff19078699675044b993f6921ad0

Add new error message for unreachable else prongs

* Adds error message for types: enum, int and bool * Adds compile error tests

2 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 });
470470
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 {