Browse Source

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.
Roland Kovacs 1 year ago
parent
commit
9eb7186cda
2 changed files with 15 additions and 1 deletions
  1. 3 1
      src/check_decl.cpp
  2. 12 0
      src/checker.cpp

+ 3 - 1
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->flags |= EntityFlag_Overridden;
 	original_entity->type = new_entity->type;
 	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->aliased_of = new_entity;
 
 
 	original_entity->identifier.store(new_entity->identifier);
 	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
 	// 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 offset = cast(u8 *)&original_entity->Dummy.start - cast(u8 *)original_entity;
 	isize size = gb_size_of(*original_entity) - offset;
 	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) {
 gb_internal bool check_override_as_type_due_to_aliasing(CheckerContext *ctx, Entity *e, Entity *entity, Ast *init, Type *named_type) {

+ 12 - 0
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) {
 	if ((e->flags & EntityFlag_ProcBodyChecked) != 0) {
 		return;
 		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);
 	Type *type = base_type(e->type);
 	if (type == t_invalid) {
 	if (type == t_invalid) {
 		return;
 		return;