diff --git a/src/check_decl.cpp b/src/check_decl.cpp index 809ccbc9b..69e7c563e 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -40,6 +40,10 @@ Type *check_init_variable(CheckerContext *ctx, Entity *e, Operand *operand, Stri return nullptr; } + if (e->kind == Entity_Variable) { + e->Variable.init_expr = operand->expr; + } + if (operand->mode == Addressing_Type) { if (e->type != nullptr && is_type_typeid(e->type)) { add_type_info_type(ctx, operand->type); diff --git a/src/checker.cpp b/src/checker.cpp index 108eedd47..eba30e737 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -506,15 +506,30 @@ bool check_vet_shadowing(Checker *c, Entity *e, VettedEntity *ve) { return false; } // NOTE(bill): If the types differ, don't complain - if (are_types_identical(e->type, shadowed->type)) { - gb_zero_item(ve); - ve->kind = VettedEntity_Shadowed; - ve->entity = e; - ve->other = shadowed; - return true; + if (!are_types_identical(e->type, shadowed->type)) { + return false; } - return false; + // NOTE(bill): Ignore intentional redeclaration + // x := x; + // Suggested in issue #637 (2020-05-11) + if ((e->flags & EntityFlag_Using) == 0 && e->kind == Entity_Variable) { + Ast *init = unparen_expr(e->Variable.init_expr); + if (init != nullptr && init->kind == Ast_Ident) { + // TODO(bill): Which logic is better? Same name or same entity + // bool ignore = init->Ident.token.string == name; + bool ignore = init->Ident.entity == shadowed; + if (ignore) { + return false; + } + } + } + + gb_zero_item(ve); + ve->kind = VettedEntity_Shadowed; + ve->entity = e; + ve->other = shadowed; + return true; } bool check_vet_unused(Checker *c, Entity *e, VettedEntity *ve) { diff --git a/src/entity.cpp b/src/entity.cpp index fdd277331..dba289305 100644 --- a/src/entity.cpp +++ b/src/entity.cpp @@ -121,6 +121,7 @@ struct Entity { ExactValue value; } Constant; struct { + Ast *init_expr; // only used for some variables within procedure bodies i32 field_index; i32 field_src_index;