From 9eb7186cda2081c7fadbc0d196346b4e57f5e4c1 Mon Sep 17 00:00:00 2001 From: Roland Kovacs Date: Sun, 11 Aug 2024 01:09:22 +0200 Subject: [PATCH] Fix alias handling of procedures An incorrect memmove when overriding entities caused multiple ones to point to the same procedure with incomplete variant data, resulting in later hiting a compiler assertion. Introduced delayed type checking for procedure aliases, as it was masked by the previous error in the override logic. --- src/check_decl.cpp | 4 +++- src/checker.cpp | 12 ++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/check_decl.cpp b/src/check_decl.cpp index a1436fe03..1425aafa8 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -180,6 +180,8 @@ gb_internal void override_entity_in_scope(Entity *original_entity, Entity *new_e original_entity->flags |= EntityFlag_Overridden; original_entity->type = new_entity->type; + original_entity->kind = new_entity->kind; + original_entity->decl_info = new_entity->decl_info; original_entity->aliased_of = new_entity; original_entity->identifier.store(new_entity->identifier); @@ -193,7 +195,7 @@ gb_internal void override_entity_in_scope(Entity *original_entity, Entity *new_e // This is most likely NEVER required, but it does not at all hurt to keep isize offset = cast(u8 *)&original_entity->Dummy.start - cast(u8 *)original_entity; isize size = gb_size_of(*original_entity) - offset; - gb_memmove(cast(u8 *)original_entity, cast(u8 *)new_entity, size); + gb_memmove(cast(u8 *)original_entity + offset, cast(u8 *)new_entity + offset, size); } gb_internal bool check_override_as_type_due_to_aliasing(CheckerContext *ctx, Entity *e, Entity *entity, Ast *init, Type *named_type) { diff --git a/src/checker.cpp b/src/checker.cpp index 60000ec29..91e7a08fe 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -5676,6 +5676,18 @@ gb_internal void check_procedure_later_from_entity(Checker *c, Entity *e, char c if ((e->flags & EntityFlag_ProcBodyChecked) != 0) { return; } + if ((e->flags & EntityFlag_Overridden) != 0) { + // NOTE (zen3ger) Delay checking of a proc alias until the underlying proc is checked. + GB_ASSERT(e->aliased_of != nullptr); + GB_ASSERT(e->aliased_of->kind == Entity_Procedure); + if ((e->aliased_of->flags & EntityFlag_ProcBodyChecked) != 0) { + e->flags |= EntityFlag_ProcBodyChecked; + return; + } + // NOTE (zen3ger) A proc alias *does not* have a body and tags! + check_procedure_later(c, e->file, e->token, e->decl_info, e->type, nullptr, 0); + return; + } Type *type = base_type(e->type); if (type == t_invalid) { return;