mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-04 14:48:47 +00:00
Fix procedure constant declaration value type assignment checking
This commit is contained in:
+54
-1
@@ -338,7 +338,7 @@ void check_const_decl(CheckerContext *ctx, Entity *e, Ast *type_expr, Ast *init,
|
|||||||
|
|
||||||
if (type_expr) {
|
if (type_expr) {
|
||||||
Type *t = check_type(ctx, type_expr);
|
Type *t = check_type(ctx, type_expr);
|
||||||
if (!is_type_constant_type(t)) {
|
if (!is_type_constant_type(t) && !is_type_proc(t)) {
|
||||||
gbString str = type_to_string(t);
|
gbString str = type_to_string(t);
|
||||||
error(type_expr, "Invalid constant type '%s'", str);
|
error(type_expr, "Invalid constant type '%s'", str);
|
||||||
gb_string_free(str);
|
gb_string_free(str);
|
||||||
@@ -392,6 +392,25 @@ void check_const_decl(CheckerContext *ctx, Entity *e, Ast *type_expr, Ast *init,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (entity != nullptr) {
|
if (entity != nullptr) {
|
||||||
|
if (e->type != nullptr) {
|
||||||
|
Operand x = {};
|
||||||
|
x.type = entity->type;
|
||||||
|
x.mode = Addressing_Variable;
|
||||||
|
if (!check_is_assignable_to(ctx, &x, e->type)) {
|
||||||
|
gbString expr_str = expr_to_string(init);
|
||||||
|
gbString op_type_str = type_to_string(entity->type);
|
||||||
|
gbString type_str = type_to_string(e->type);
|
||||||
|
error(e->token,
|
||||||
|
"Cannot assign '%s' of type '%s' to '%s'",
|
||||||
|
expr_str,
|
||||||
|
op_type_str,
|
||||||
|
type_str);
|
||||||
|
|
||||||
|
gb_string_free(type_str);
|
||||||
|
gb_string_free(op_type_str);
|
||||||
|
gb_string_free(expr_str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// NOTE(bill): Override aliased entity
|
// NOTE(bill): Override aliased entity
|
||||||
switch (entity->kind) {
|
switch (entity->kind) {
|
||||||
@@ -583,11 +602,45 @@ void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) {
|
|||||||
check_open_scope(ctx, pl->type);
|
check_open_scope(ctx, pl->type);
|
||||||
defer (check_close_scope(ctx));
|
defer (check_close_scope(ctx));
|
||||||
|
|
||||||
|
Type *decl_type = nullptr;
|
||||||
|
|
||||||
|
if (d->type_expr != nullptr) {
|
||||||
|
decl_type = check_type(ctx, d->type_expr);
|
||||||
|
if (!is_type_proc(decl_type)) {
|
||||||
|
gbString str = type_to_string(decl_type);
|
||||||
|
error(d->type_expr, "Expected a procedure type, got '%s'", str);
|
||||||
|
gb_string_free(str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
auto tmp_ctx = *ctx;
|
auto tmp_ctx = *ctx;
|
||||||
tmp_ctx.allow_polymorphic_types = true;
|
tmp_ctx.allow_polymorphic_types = true;
|
||||||
|
if (decl_type != nullptr) {
|
||||||
|
tmp_ctx.type_hint = decl_type;
|
||||||
|
}
|
||||||
check_procedure_type(&tmp_ctx, proc_type, pl->type);
|
check_procedure_type(&tmp_ctx, proc_type, pl->type);
|
||||||
|
|
||||||
|
if (decl_type != nullptr) {
|
||||||
|
Operand x = {};
|
||||||
|
x.type = e->type;
|
||||||
|
x.mode = Addressing_Variable;
|
||||||
|
if (!check_is_assignable_to(ctx, &x, decl_type)) {
|
||||||
|
gbString expr_str = expr_to_string(d->proc_lit);
|
||||||
|
gbString op_type_str = type_to_string(e->type);
|
||||||
|
gbString type_str = type_to_string(decl_type);
|
||||||
|
error(e->token,
|
||||||
|
"Cannot assign '%s' of type '%s' to '%s'",
|
||||||
|
expr_str,
|
||||||
|
op_type_str,
|
||||||
|
type_str);
|
||||||
|
|
||||||
|
gb_string_free(type_str);
|
||||||
|
gb_string_free(op_type_str);
|
||||||
|
gb_string_free(expr_str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TypeProc *pt = &proc_type->Proc;
|
TypeProc *pt = &proc_type->Proc;
|
||||||
AttributeContext ac = make_attribute_context(e->Procedure.link_prefix);
|
AttributeContext ac = make_attribute_context(e->Procedure.link_prefix);
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -2591,7 +2591,7 @@ void check_collect_value_decl(CheckerContext *c, Ast *decl) {
|
|||||||
pl->type->ProcType.calling_convention = cc;
|
pl->type->ProcType.calling_convention = cc;
|
||||||
}
|
}
|
||||||
d->proc_lit = init;
|
d->proc_lit = init;
|
||||||
d->type_expr = pl->type;
|
d->type_expr = vd->type;
|
||||||
} else if (init->kind == Ast_ProcGroup) {
|
} else if (init->kind == Ast_ProcGroup) {
|
||||||
ast_node(pg, ProcGroup, init);
|
ast_node(pg, ProcGroup, init);
|
||||||
e = alloc_entity_proc_group(d->scope, token, nullptr);
|
e = alloc_entity_proc_group(d->scope, token, nullptr);
|
||||||
@@ -2599,6 +2599,7 @@ void check_collect_value_decl(CheckerContext *c, Ast *decl) {
|
|||||||
error(name, "Procedure groups are not allowed within a foreign block");
|
error(name, "Procedure groups are not allowed within a foreign block");
|
||||||
}
|
}
|
||||||
d->init_expr = init;
|
d->init_expr = init;
|
||||||
|
d->type_expr = vd->type;
|
||||||
} else {
|
} else {
|
||||||
e = alloc_entity_constant(d->scope, token, nullptr, empty_exact_value);
|
e = alloc_entity_constant(d->scope, token, nullptr, empty_exact_value);
|
||||||
d->type_expr = vd->type;
|
d->type_expr = vd->type;
|
||||||
|
|||||||
Reference in New Issue
Block a user