mirror of
https://github.com/odin-lang/Odin.git
synced 2026-03-03 07:08:20 +00:00
Fix addressing mode rules for match in statements
This commit is contained in:
@@ -1142,6 +1142,9 @@ Entity *check_ident(Checker *c, Operand *o, AstNode *n, Type *named_type, Type *
|
||||
return e;
|
||||
}
|
||||
o->mode = Addressing_Variable;
|
||||
if (e->flags & EntityFlag_Value) {
|
||||
o->mode = Addressing_Value;
|
||||
}
|
||||
if (e->Variable.is_immutable) {
|
||||
o->mode = Addressing_Immutable;
|
||||
}
|
||||
|
||||
@@ -1058,6 +1058,8 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
||||
break;
|
||||
}
|
||||
|
||||
bool is_ptr = is_type_pointer(x.type);
|
||||
|
||||
// NOTE(bill): Check for multiple defaults
|
||||
AstNode *first_default = NULL;
|
||||
ast_node(bs, BlockStmt, ms->body);
|
||||
@@ -1153,6 +1155,13 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
||||
}
|
||||
}
|
||||
|
||||
if (is_ptr &&
|
||||
!is_type_any(type_deref(x.type)) &&
|
||||
cc->list.count == 1 &&
|
||||
case_type != NULL) {
|
||||
case_type = make_type_pointer(c->allocator, case_type);
|
||||
}
|
||||
|
||||
if (cc->list.count > 1) {
|
||||
case_type = NULL;
|
||||
}
|
||||
@@ -1163,8 +1172,9 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
||||
|
||||
check_open_scope(c, stmt);
|
||||
{
|
||||
Entity *tag_var = make_entity_variable(c->allocator, c->context.scope, lhs->Ident, case_type, true);
|
||||
Entity *tag_var = make_entity_variable(c->allocator, c->context.scope, lhs->Ident, case_type, false);
|
||||
tag_var->flags |= EntityFlag_Used;
|
||||
tag_var->flags |= EntityFlag_Value;
|
||||
add_entity(c, c->context.scope, lhs, tag_var);
|
||||
add_entity_use(c, lhs, tag_var);
|
||||
add_implicit_entity(c, stmt, tag_var);
|
||||
|
||||
@@ -40,6 +40,7 @@ typedef enum EntityFlag {
|
||||
EntityFlag_Ellipsis = 1<<6,
|
||||
EntityFlag_NoAlias = 1<<7,
|
||||
EntityFlag_TypeField = 1<<8,
|
||||
EntityFlag_Value = 1<<9,
|
||||
} EntityFlag;
|
||||
|
||||
// Zero value means the overloading process is not yet done
|
||||
|
||||
13
src/ir.c
13
src/ir.c
@@ -6239,7 +6239,13 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
||||
ir_start_block(proc, body);
|
||||
|
||||
if (cc->list.count == 1) {
|
||||
Type *ct = make_type_pointer(proc->module->allocator, case_entity->type);
|
||||
bool any_or_not_ptr = is_type_any(type_deref(parent_type)) || !is_parent_ptr;
|
||||
|
||||
Type *ct = case_entity->type;
|
||||
if (any_or_not_ptr) {
|
||||
ct = make_type_pointer(proc->module->allocator, ct);
|
||||
}
|
||||
GB_ASSERT_MSG(is_type_pointer(ct), "%s", type_to_string(ct));
|
||||
irValue *data = NULL;
|
||||
if (match_type_kind == MatchType_Union) {
|
||||
data = union_data;
|
||||
@@ -6247,7 +6253,10 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
||||
irValue *any_data = ir_emit_load(proc, ir_emit_struct_ep(proc, parent_ptr, 1));
|
||||
data = any_data;
|
||||
}
|
||||
value = ir_emit_load(proc, ir_emit_conv(proc, data, ct));
|
||||
value = ir_emit_conv(proc, data, ct);
|
||||
if (any_or_not_ptr) {
|
||||
value = ir_emit_load(proc, value);
|
||||
}
|
||||
}
|
||||
|
||||
ir_store_type_case_implicit(proc, clause, value);
|
||||
|
||||
Reference in New Issue
Block a user