diff options
Diffstat (limited to 'src/checker.cpp')
| -rw-r--r-- | src/checker.cpp | 88 |
1 files changed, 53 insertions, 35 deletions
diff --git a/src/checker.cpp b/src/checker.cpp index 0253bc86b..130c4aee5 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -388,8 +388,7 @@ Entity *scope_lookup(Scope *s, String name) { -Entity *scope_insert(Scope *s, Entity *entity) { - String name = entity->token.string; +Entity *scope_insert_with_name(Scope *s, String name, Entity *entity) { if (name == "") { return nullptr; } @@ -406,6 +405,11 @@ Entity *scope_insert(Scope *s, Entity *entity) { return nullptr; } +Entity *scope_insert(Scope *s, Entity *entity) { + String name = entity->token.string; + return scope_insert_with_name(s, name, entity); +} + GB_COMPARE_PROC(entity_variable_pos_cmp) { Entity *x = *cast(Entity **)a; @@ -1023,39 +1027,41 @@ void add_entity_definition(CheckerInfo *i, Ast *identifier, Entity *entity) { array_add(&i->definitions, entity); } -bool add_entity(Checker *c, Scope *scope, Ast *identifier, Entity *entity) { +bool redeclaration_error(String name, Entity *prev, Entity *found) { + TokenPos pos = found->token.pos; + Entity *up = found->using_parent; + if (up != nullptr) { + if (pos == up->token.pos) { + // NOTE(bill): Error should have been handled already + return false; + } + error(prev->token, + "Redeclaration of '%.*s' in this scope through 'using'\n" + "\tat %.*s(%td:%td)", + LIT(name), + LIT(up->token.pos.file), up->token.pos.line, up->token.pos.column); + } else { + if (pos == prev->token.pos) { + // NOTE(bill): Error should have been handled already + return false; + } + error(prev->token, + "Redeclaration of '%.*s' in this scope\n" + "\tat %.*s(%td:%td)", + LIT(name), + LIT(pos.file), pos.line, pos.column); + } + return false; +} + +bool add_entity_with_name(Checker *c, Scope *scope, Ast *identifier, Entity *entity, String name) { if (scope == nullptr) { return false; } - String name = entity->token.string; if (!is_blank_ident(name)) { Entity *ie = scope_insert(scope, entity); if (ie != nullptr) { - TokenPos pos = ie->token.pos; - Entity *up = ie->using_parent; - if (up != nullptr) { - if (pos == up->token.pos) { - // NOTE(bill): Error should have been handled already - return false; - } - error(entity->token, - "Redeclaration of '%.*s' in this scope through 'using'\n" - "\tat %.*s(%td:%td)", - LIT(name), - LIT(up->token.pos.file), up->token.pos.line, up->token.pos.column); - return false; - } else { - if (pos == entity->token.pos) { - // NOTE(bill): Error should have been handled already - return false; - } - error(entity->token, - "Redeclaration of '%.*s' in this scope\n" - "\tat %.*s(%td:%td)", - LIT(name), - LIT(pos.file), pos.line, pos.column); - return false; - } + return redeclaration_error(name, entity, ie); } } if (identifier != nullptr) { @@ -1063,6 +1069,9 @@ bool add_entity(Checker *c, Scope *scope, Ast *identifier, Entity *entity) { } return true; } +bool add_entity(Checker *c, Scope *scope, Ast *identifier, Entity *entity) { + return add_entity_with_name(c, scope, identifier, entity, entity->token.string); +} void add_entity_use(CheckerContext *c, Ast *identifier, Entity *entity) { if (entity == nullptr) { @@ -2005,7 +2014,7 @@ DECL_ATTRIBUTE_PROC(proc_decl_attribute) { if (value != nullptr) { Operand o = {}; check_expr(c, &o, value); - Entity *e = entity_of_ident(o.expr); + Entity *e = entity_of_node(o.expr); if (e != nullptr && e->kind == Entity_Procedure) { warning(elem, "'%.*s' is deprecated, please use one of the following instead: 'deferred_none', 'deferred_in', 'deferred_out'", LIT(name)); if (ac->deferred_procedure.entity != nullptr) { @@ -2022,7 +2031,7 @@ DECL_ATTRIBUTE_PROC(proc_decl_attribute) { if (value != nullptr) { Operand o = {}; check_expr(c, &o, value); - Entity *e = entity_of_ident(o.expr); + Entity *e = entity_of_node(o.expr); if (e != nullptr && e->kind == Entity_Procedure) { ac->deferred_procedure.kind = DeferredProcedure_none; ac->deferred_procedure.entity = e; @@ -2035,7 +2044,7 @@ DECL_ATTRIBUTE_PROC(proc_decl_attribute) { if (value != nullptr) { Operand o = {}; check_expr(c, &o, value); - Entity *e = entity_of_ident(o.expr); + Entity *e = entity_of_node(o.expr); if (e != nullptr && e->kind == Entity_Procedure) { if (ac->deferred_procedure.entity != nullptr) { error(elem, "Previous usage of a 'deferred_*' attribute"); @@ -2051,7 +2060,7 @@ DECL_ATTRIBUTE_PROC(proc_decl_attribute) { if (value != nullptr) { Operand o = {}; check_expr(c, &o, value); - Entity *e = entity_of_ident(o.expr); + Entity *e = entity_of_node(o.expr); if (e != nullptr && e->kind == Entity_Procedure) { if (ac->deferred_procedure.entity != nullptr) { error(elem, "Previous usage of a 'deferred_*' attribute"); @@ -3050,12 +3059,21 @@ void check_add_import_decl(CheckerContext *ctx, Ast *decl) { // NOTE(bill): Add imported entities to this file's scope for_array(elem_index, scope->elements.entries) { + String name = scope->elements.entries[elem_index].key.string; Entity *e = scope->elements.entries[elem_index].value; if (e->scope == parent_scope) continue; if (is_entity_exported(e)) { - Entity *prev = scope_lookup(parent_scope, e->token.string); - add_entity(ctx->checker, parent_scope, e->identifier, e); + Entity *found = scope_lookup_current(parent_scope, name); + if (found != nullptr) { + // NOTE(bill): + // Date: 2019-03-17 + // The order has to be the other way around as `using` adds the entity into the that + // file scope otherwise the error would be the wrong way around + redeclaration_error(name, found, e); + } else { + add_entity_with_name(ctx->checker, parent_scope, e->identifier, e, name); + } } } } |