From 7261cd19b78367d78f758f7ade370efbc3e25237 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 7 May 2017 13:40:35 -0400 Subject: detect duplicate switch value even when else prong present closes #43 --- src/ir.cpp | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) (limited to 'src/ir.cpp') diff --git a/src/ir.cpp b/src/ir.cpp index f5ced359ba..53f2a48d74 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -2015,13 +2015,15 @@ static IrInstruction *ir_build_err_to_int(IrBuilder *irb, Scope *scope, AstNode } static IrInstruction *ir_build_check_switch_prongs(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *target_value, IrInstructionCheckSwitchProngsRange *ranges, size_t range_count) + IrInstruction *target_value, IrInstructionCheckSwitchProngsRange *ranges, size_t range_count, + bool have_else_prong) { IrInstructionCheckSwitchProngs *instruction = ir_build_instruction( irb, scope, source_node); instruction->target_value = target_value; instruction->ranges = ranges; instruction->range_count = range_count; + instruction->have_else_prong = have_else_prong; ir_ref_instruction(target_value, irb->current_basic_block); for (size_t i = 0; i < range_count; i += 1) { @@ -5542,9 +5544,8 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * } } - if (!else_prong) { - ir_build_check_switch_prongs(irb, scope, node, target_value, check_ranges.items, check_ranges.length); - } + ir_build_check_switch_prongs(irb, scope, node, target_value, check_ranges.items, check_ranges.length, + else_prong != nullptr); if (cases.length == 0) { ir_build_br(irb, scope, node, else_block, is_comptime); @@ -13019,11 +13020,13 @@ static TypeTableEntry *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira field_prev_uses[field_index] = start_value->source_node; } } - for (uint32_t i = 0; i < enum_type->data.enumeration.src_field_count; i += 1) { - if (field_prev_uses[i] == nullptr) { - ir_add_error(ira, &instruction->base, - buf_sprintf("enumeration value '%s.%s' not handled in switch", buf_ptr(&enum_type->name), - buf_ptr(enum_type->data.enumeration.fields[i].name))); + if (!instruction->have_else_prong) { + for (uint32_t i = 0; i < enum_type->data.enumeration.src_field_count; i += 1) { + if (field_prev_uses[i] == nullptr) { + ir_add_error(ira, &instruction->base, + buf_sprintf("enumeration value '%s.%s' not handled in switch", buf_ptr(&enum_type->name), + buf_ptr(enum_type->data.enumeration.fields[i].name))); + } } } } else if (switch_type->id == TypeTableEntryIdInt) { @@ -13055,15 +13058,17 @@ static TypeTableEntry *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira return ira->codegen->builtin_types.entry_invalid; } } - BigNum min_val; - eval_min_max_value_int(ira->codegen, switch_type, &min_val, false); - BigNum max_val; - eval_min_max_value_int(ira->codegen, switch_type, &max_val, true); - if (!rangeset_spans(&rs, &min_val, &max_val)) { - ir_add_error(ira, &instruction->base, buf_sprintf("switch must handle all possibilities")); - return ira->codegen->builtin_types.entry_invalid; + if (!instruction->have_else_prong) { + BigNum min_val; + eval_min_max_value_int(ira->codegen, switch_type, &min_val, false); + BigNum max_val; + eval_min_max_value_int(ira->codegen, switch_type, &max_val, true); + if (!rangeset_spans(&rs, &min_val, &max_val)) { + ir_add_error(ira, &instruction->base, buf_sprintf("switch must handle all possibilities")); + return ira->codegen->builtin_types.entry_invalid; + } } - } else { + } else if (!instruction->have_else_prong) { ir_add_error(ira, &instruction->base, buf_sprintf("else prong required when switching on type '%s'", buf_ptr(&switch_type->name))); return ira->codegen->builtin_types.entry_invalid; -- cgit v1.2.3