mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-07 16:18:52 +00:00
Fix compile time issue regarding switch ranges
This commit is contained in:
+15
-14
@@ -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 &&
|
lhs.mode == Addressing_Constant && rhs.mode == Addressing_Constant &&
|
||||||
is_type_number(lhs.type) && is_type_number(rhs.type)) {
|
is_type_number(lhs.type) && is_type_number(rhs.type)) {
|
||||||
ExactValue start = lhs.value;
|
ExactValue start = lhs.value;
|
||||||
@@ -852,21 +853,21 @@ void check_switch_stmt(Checker *c, AstNode *node, u32 mod_flags) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
enum SwitchKind {
|
enum TypeSwitchKind {
|
||||||
Switch_Invalid,
|
TypeSwitch_Invalid,
|
||||||
Switch_Union,
|
TypeSwitch_Union,
|
||||||
Switch_Any,
|
TypeSwitch_Any,
|
||||||
};
|
};
|
||||||
|
|
||||||
SwitchKind check_valid_type_switch_type(Type *type) {
|
TypeSwitchKind check_valid_type_switch_type(Type *type) {
|
||||||
type = type_deref(type);
|
type = type_deref(type);
|
||||||
if (is_type_union(type)) {
|
if (is_type_union(type)) {
|
||||||
return Switch_Union;
|
return TypeSwitch_Union;
|
||||||
}
|
}
|
||||||
if (is_type_any(type)) {
|
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) {
|
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?
|
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) {
|
if (ss->tag->kind != AstNode_AssignStmt) {
|
||||||
error(ss->tag, "Expected an 'in' assignment for this type switch statement");
|
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_expr(c, &x, rhs);
|
||||||
check_assignment(c, &x, nullptr, str_lit("type switch expression"));
|
check_assignment(c, &x, nullptr, str_lit("type switch expression"));
|
||||||
switch_kind = check_valid_type_switch_type(x.type);
|
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);
|
gbString str = type_to_string(x.type);
|
||||||
error(x.expr, "Invalid type for this type switch expression, got '%s'", str);
|
error(x.expr, "Invalid type for this type switch expression, got '%s'", str);
|
||||||
gb_string_free(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;
|
bool complete = ss->complete;
|
||||||
if (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");
|
error(node, "#complete switch statement may only be used with a union");
|
||||||
complete = false;
|
complete = false;
|
||||||
}
|
}
|
||||||
@@ -973,7 +974,7 @@ void check_type_switch_stmt(Checker *c, AstNode *node, u32 mod_flags) {
|
|||||||
Operand y = {};
|
Operand y = {};
|
||||||
check_expr_or_type(c, &y, type_expr);
|
check_expr_or_type(c, &y, type_expr);
|
||||||
|
|
||||||
if (switch_kind == Switch_Union) {
|
if (switch_kind == TypeSwitch_Union) {
|
||||||
GB_ASSERT(is_type_union(bt));
|
GB_ASSERT(is_type_union(bt));
|
||||||
bool tag_type_found = false;
|
bool tag_type_found = false;
|
||||||
for_array(i, bt->Union.variants) {
|
for_array(i, bt->Union.variants) {
|
||||||
@@ -990,7 +991,7 @@ void check_type_switch_stmt(Checker *c, AstNode *node, u32 mod_flags) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
case_type = y.type;
|
case_type = y.type;
|
||||||
} else if (switch_kind == Switch_Any) {
|
} else if (switch_kind == TypeSwitch_Any) {
|
||||||
case_type = y.type;
|
case_type = y.type;
|
||||||
} else {
|
} else {
|
||||||
GB_PANIC("Unknown type to type switch statement");
|
GB_PANIC("Unknown type to type switch statement");
|
||||||
|
|||||||
+12
-22
@@ -7177,8 +7177,8 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
|||||||
Type *parent_type = ir_type(parent);
|
Type *parent_type = ir_type(parent);
|
||||||
bool is_parent_ptr = is_type_pointer(ir_type(parent));
|
bool is_parent_ptr = is_type_pointer(ir_type(parent));
|
||||||
|
|
||||||
SwitchKind switch_kind = check_valid_type_switch_type(ir_type(parent));
|
TypeSwitchKind switch_kind = check_valid_type_switch_type(ir_type(parent));
|
||||||
GB_ASSERT(switch_kind != Switch_Invalid);
|
GB_ASSERT(switch_kind != TypeSwitch_Invalid);
|
||||||
|
|
||||||
irValue *parent_value = parent;
|
irValue *parent_value = parent;
|
||||||
|
|
||||||
@@ -7189,7 +7189,7 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
|||||||
|
|
||||||
irValue *tag_index = nullptr;
|
irValue *tag_index = nullptr;
|
||||||
irValue *union_data = 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"));
|
ir_emit_comment(proc, str_lit("get union's tag"));
|
||||||
tag_index = ir_emit_load(proc, ir_emit_union_tag_ptr(proc, parent_ptr));
|
tag_index = ir_emit_load(proc, ir_emit_union_tag_ptr(proc, parent_ptr));
|
||||||
union_data = ir_emit_conv(proc, parent_ptr, t_rawptr);
|
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");
|
next = ir_new_block(proc, nullptr, "typeswitch.next");
|
||||||
case_type = type_of_expr(proc->module->info, cc->list[type_index]);
|
case_type = type_of_expr(proc->module->info, cc->list[type_index]);
|
||||||
irValue *cond = nullptr;
|
irValue *cond = nullptr;
|
||||||
if (switch_kind == Switch_Union) {
|
if (switch_kind == TypeSwitch_Union) {
|
||||||
Type *ut = base_type(type_deref(parent_type));
|
Type *ut = base_type(type_deref(parent_type));
|
||||||
irValue *variant_tag = ir_const_union_tag(proc->module->allocator, ut, case_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);
|
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 *any_ti = ir_emit_load(proc, ir_emit_struct_ep(proc, parent_ptr, 1));
|
||||||
irValue *case_ti = ir_type_info(proc, case_type);
|
irValue *case_ti = ir_type_info(proc, case_type);
|
||||||
cond = ir_emit_comp(proc, Token_CmpEq, any_ti, case_ti);
|
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));
|
GB_ASSERT_MSG(is_type_pointer(ct), "%s", type_to_string(ct));
|
||||||
irValue *data = nullptr;
|
irValue *data = nullptr;
|
||||||
if (switch_kind == Switch_Union) {
|
if (switch_kind == TypeSwitch_Union) {
|
||||||
data = union_data;
|
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));
|
irValue *any_data = ir_emit_load(proc, ir_emit_struct_ep(proc, parent_ptr, 0));
|
||||||
data = any_data;
|
data = any_data;
|
||||||
}
|
}
|
||||||
@@ -7291,22 +7291,12 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
switch (bs->token.kind) {
|
for (irTargetList *t = proc->target_list; t != nullptr && block == nullptr; t = t->prev) {
|
||||||
case Token_break:
|
switch (bs->token.kind) {
|
||||||
for (irTargetList *t = proc->target_list; t != nullptr && block == nullptr; t = t->prev) {
|
case Token_break: block = t->break_; break;
|
||||||
block = t->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) {
|
if (block != nullptr) {
|
||||||
|
|||||||
Reference in New Issue
Block a user