commit 858404bda6a1a4cbc789905d1028ae73f98e7cbf
parent 2eccbc4b959a590dda91143c8487edda841106d9
Author: Armin Weigl <tb46305@gmail.com>
Date: Tue, 21 Jun 2022 21:48:00 +0200
check: replace ctx.resolving_enum with ctx.scope
solving an issue related to shadowing variables withhin enum scopes on
the way
Signed-off-by: Armin Weigl <tb46305@gmail.com>
Diffstat:
3 files changed, 15 insertions(+), 19 deletions(-)
diff --git a/include/check.h b/include/check.h
@@ -41,7 +41,6 @@ struct context {
bool is_test;
struct scope *unit;
struct scope *scope;
- struct scope *resolving_enum;
bool deferring;
int id;
struct errors *errors;
diff --git a/src/check.c b/src/check.c
@@ -146,12 +146,7 @@ check_expr_access(struct context *ctx,
const struct scope_object *obj = NULL;
switch (expr->access.type) {
case ACCESS_IDENTIFIER:
- if (ctx->resolving_enum) {
- obj = scope_lookup(ctx->resolving_enum, &aexpr->access.ident);
- }
- if (!obj) {
- obj = scope_lookup(ctx->scope, &aexpr->access.ident);
- }
+ obj = scope_lookup(ctx->scope, &aexpr->access.ident);
if (!obj) {
char buf[1024];
identifier_unparse_static(&aexpr->access.ident,
@@ -3504,6 +3499,7 @@ incomplete_types_create(struct context *ctx, struct scope *imp, struct ast_decl
scope_push((struct scope **)&type->_enum.values, SCOPE_ENUM);
incomplete_enum_field_create(ctx, imp,
type->_enum.values, type, t->type->_enum.values);
+ type->_enum.values->parent = ctx->unit;
scope_insert(ctx->scope, O_TYPE, &with_ns,
&t->ident, type, NULL);
} else {
@@ -3621,7 +3617,6 @@ resolve_enum_field(struct context *ctx, const struct scope_object *obj)
{
assert(obj->otype == O_SCAN);
struct incomplete_declaration *idecl = (struct incomplete_declaration*)obj;
- assert(ctx->resolving_enum == NULL);
assert(idecl->type == IDECL_ENUM_FLD);
const struct type *type = idecl->field->type;
@@ -3658,7 +3653,7 @@ resolve_enum_field(struct context *ctx, const struct scope_object *obj)
idecl = (struct incomplete_declaration *)obj;
assert(idecl->type == IDECL_ENUM_FLD);
- ctx->resolving_enum = idecl->field->enum_scope;
+ ctx->scope = idecl->field->enum_scope;
struct expression *value = xcalloc(1, sizeof(struct expression));
value->result = type;
if (idecl->field->field->value) { // explicit value
@@ -3704,7 +3699,6 @@ resolve_enum_field(struct context *ctx, const struct scope_object *obj)
}
}
}
- ctx->resolving_enum = NULL;
return scope_insert(idecl->field->enum_scope, O_CONST, &name, &localname, type, value);
}
@@ -3972,8 +3966,7 @@ wrap_resolver(struct context *ctx, const struct scope_object *obj,
resolvefn resolver)
{
// save current subunit and enum context
- struct scope *enum_scope = ctx->resolving_enum;
- ctx->resolving_enum = NULL;
+ struct scope *scope = ctx->scope;
struct scope *subunit = ctx->unit->parent;
ctx->unit->parent = NULL;
@@ -3985,6 +3978,7 @@ wrap_resolver(struct context *ctx, const struct scope_object *obj,
}
// load this declaration's subunit context
+ ctx->scope = ctx->unit;
ctx->unit->parent = idecl->imports;
// resolving a declaration that is already in progress -> cycle
@@ -4005,7 +3999,7 @@ wrap_resolver(struct context *ctx, const struct scope_object *obj,
exit:
// load stored context
ctx->unit->parent = subunit;
- ctx->resolving_enum = enum_scope;
+ ctx->scope = scope;
idecl->in_progress = false;
return obj;
}
@@ -4233,14 +4227,12 @@ check_internal(struct type_store *ts,
}
// Perform actual declaration resolution
- ctx.resolving_enum = NULL;
for (const struct scope_object *obj = ctx.scope->objects;
obj; obj = obj->lnext) {
if (obj->otype != O_SCAN) {
continue;
}
wrap_resolver(&ctx, obj, resolve_decl);
- assert(ctx.resolving_enum == NULL);
}
handle_errors(ctx.errors);
diff --git a/tests/15-enums.ha b/tests/15-enums.ha
@@ -129,16 +129,19 @@ fn aliases() void = {
assert(imported_double_alias::THREE == testmod::_enum::THREE);
};
-// Force T2 to be resolved before T1
+// Force T2 to be resolved before t2::T3 and t2::T3 before t2::T1
type t1 = enum {
I1 = t2::T1,
- I2 = t2::T2,
+ I2 = t2::T3,
+ I3 = T2: int,
};
+def T2: uint = 0;
+
type t2 = enum {
T1,
T2 = 1,
- T3,
+ T3 = T2 + 1,
};
export fn resolution_order() void = {
@@ -146,7 +149,9 @@ export fn resolution_order() void = {
assert(t2::T2 == 1);
assert(t2::T3 == 2);
assert(t1::I1 == 0);
- assert(t1::I2 == 1);
+ assert(t1::I2 == 2);
+ assert(t1::I3 == 0);
+ assert(T2 == 0);
};
export fn main() void = {