From d560f6c920095465be71f19b3e34c836966ff5c6 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 17 Feb 2018 19:05:14 +0000 Subject: [PATCH] Fix compile time issue regarding switch ranges --- src/check_stmt.cpp | 29 +++++++++++++++-------------- src/ir.cpp | 34 ++++++++++++---------------------- 2 files changed, 27 insertions(+), 36 deletions(-) diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index a8208b7dd..6961d6b2e 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -744,7 +744,8 @@ void check_switch_stmt(Checker *c, AstNode *node, u32 mod_flags) { } } - if (a1.mode != Addressing_Invalid && b1.mode != Addressing_Invalid && + if (complete && + a1.mode != Addressing_Invalid && b1.mode != Addressing_Invalid && lhs.mode == Addressing_Constant && rhs.mode == Addressing_Constant && is_type_number(lhs.type) && is_type_number(rhs.type)) { ExactValue start = lhs.value; @@ -852,21 +853,21 @@ void check_switch_stmt(Checker *c, AstNode *node, u32 mod_flags) { } -enum SwitchKind { - Switch_Invalid, - Switch_Union, - Switch_Any, +enum TypeSwitchKind { + TypeSwitch_Invalid, + TypeSwitch_Union, + TypeSwitch_Any, }; -SwitchKind check_valid_type_switch_type(Type *type) { +TypeSwitchKind check_valid_type_switch_type(Type *type) { type = type_deref(type); if (is_type_union(type)) { - return Switch_Union; + return TypeSwitch_Union; } if (is_type_any(type)) { - return Switch_Any; + return TypeSwitch_Any; } - return Switch_Invalid; + return TypeSwitch_Invalid; } void check_type_switch_stmt(Checker *c, AstNode *node, u32 mod_flags) { @@ -879,7 +880,7 @@ void check_type_switch_stmt(Checker *c, AstNode *node, u32 mod_flags) { check_label(c, ss->label); // TODO(bill): What should the label's "scope" be? - SwitchKind switch_kind = Switch_Invalid; + TypeSwitchKind switch_kind = TypeSwitch_Invalid; if (ss->tag->kind != AstNode_AssignStmt) { error(ss->tag, "Expected an 'in' assignment for this type switch statement"); @@ -902,7 +903,7 @@ void check_type_switch_stmt(Checker *c, AstNode *node, u32 mod_flags) { check_expr(c, &x, rhs); check_assignment(c, &x, nullptr, str_lit("type switch expression")); switch_kind = check_valid_type_switch_type(x.type); - if (switch_kind == Switch_Invalid) { + if (switch_kind == TypeSwitch_Invalid) { gbString str = type_to_string(x.type); error(x.expr, "Invalid type for this type switch expression, got '%s'", str); gb_string_free(str); @@ -911,7 +912,7 @@ void check_type_switch_stmt(Checker *c, AstNode *node, u32 mod_flags) { bool complete = ss->complete; if (complete) { - if (switch_kind != Switch_Union) { + if (switch_kind != TypeSwitch_Union) { error(node, "#complete switch statement may only be used with a union"); complete = false; } @@ -973,7 +974,7 @@ void check_type_switch_stmt(Checker *c, AstNode *node, u32 mod_flags) { Operand y = {}; check_expr_or_type(c, &y, type_expr); - if (switch_kind == Switch_Union) { + if (switch_kind == TypeSwitch_Union) { GB_ASSERT(is_type_union(bt)); bool tag_type_found = false; for_array(i, bt->Union.variants) { @@ -990,7 +991,7 @@ void check_type_switch_stmt(Checker *c, AstNode *node, u32 mod_flags) { continue; } case_type = y.type; - } else if (switch_kind == Switch_Any) { + } else if (switch_kind == TypeSwitch_Any) { case_type = y.type; } else { GB_PANIC("Unknown type to type switch statement"); diff --git a/src/ir.cpp b/src/ir.cpp index 2fb398273..f0d0c4606 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -7177,8 +7177,8 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) { Type *parent_type = ir_type(parent); bool is_parent_ptr = is_type_pointer(ir_type(parent)); - SwitchKind switch_kind = check_valid_type_switch_type(ir_type(parent)); - GB_ASSERT(switch_kind != Switch_Invalid); + TypeSwitchKind switch_kind = check_valid_type_switch_type(ir_type(parent)); + GB_ASSERT(switch_kind != TypeSwitch_Invalid); irValue *parent_value = parent; @@ -7189,7 +7189,7 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) { irValue *tag_index = nullptr; irValue *union_data = nullptr; - if (switch_kind == Switch_Union) { + if (switch_kind == TypeSwitch_Union) { ir_emit_comment(proc, str_lit("get union's tag")); tag_index = ir_emit_load(proc, ir_emit_union_tag_ptr(proc, parent_ptr)); union_data = ir_emit_conv(proc, parent_ptr, t_rawptr); @@ -7222,11 +7222,11 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) { next = ir_new_block(proc, nullptr, "typeswitch.next"); case_type = type_of_expr(proc->module->info, cc->list[type_index]); irValue *cond = nullptr; - if (switch_kind == Switch_Union) { + if (switch_kind == TypeSwitch_Union) { Type *ut = base_type(type_deref(parent_type)); irValue *variant_tag = ir_const_union_tag(proc->module->allocator, ut, case_type); cond = ir_emit_comp(proc, Token_CmpEq, tag_index, variant_tag); - } else if (switch_kind == Switch_Any) { + } else if (switch_kind == TypeSwitch_Any) { irValue *any_ti = ir_emit_load(proc, ir_emit_struct_ep(proc, parent_ptr, 1)); irValue *case_ti = ir_type_info(proc, case_type); cond = ir_emit_comp(proc, Token_CmpEq, any_ti, case_ti); @@ -7252,9 +7252,9 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) { } GB_ASSERT_MSG(is_type_pointer(ct), "%s", type_to_string(ct)); irValue *data = nullptr; - if (switch_kind == Switch_Union) { + if (switch_kind == TypeSwitch_Union) { data = union_data; - } else if (switch_kind == Switch_Any) { + } else if (switch_kind == TypeSwitch_Any) { irValue *any_data = ir_emit_load(proc, ir_emit_struct_ep(proc, parent_ptr, 0)); data = any_data; } @@ -7291,22 +7291,12 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) { break; } } else { - switch (bs->token.kind) { - case Token_break: - for (irTargetList *t = proc->target_list; t != nullptr && block == nullptr; t = t->prev) { - block = t->break_; + for (irTargetList *t = proc->target_list; t != nullptr && block == nullptr; t = t->prev) { + switch (bs->token.kind) { + case Token_break: block = t->break_; break; + case Token_continue: block = t->continue_; break; + case Token_fallthrough: block = t->fallthrough_; break; } - break; - case Token_continue: - for (irTargetList *t = proc->target_list; t != nullptr && block == nullptr; t = t->prev) { - block = t->continue_; - } - break; - case Token_fallthrough: - for (irTargetList *t = proc->target_list; t != nullptr && block == nullptr; t = t->prev) { - block = t->fallthrough_; - } - break; } } if (block != nullptr) {