From 8e655a0786aec5e0215e09f2a9629c6f32e34793 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Fri, 28 Aug 2026 02:39:42 +0200 Subject: Reject declarations shadowing imports --- boot/name_analysis.cc | 55 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 42 insertions(+), 13 deletions(-) (limited to 'boot/name_analysis.cc') diff --git a/boot/name_analysis.cc b/boot/name_analysis.cc index 30d3cda..10b8a8d 100644 --- a/boot/name_analysis.cc +++ b/boot/name_analysis.cc @@ -24,7 +24,7 @@ along with GCC; see the file COPYING3. If not see namespace elna::boot { declaration_error::declaration_error(const source_position position, const std::string& name, payload_type payload) - : diagnostic(position), name(name), payload(payload) + : diagnostic(position), name(name), payload(std::move(payload)) { } @@ -57,11 +57,12 @@ namespace elna::boot }, this->payload); } - std::optional> declaration_error::note() const + std::optional declaration_error::note() const { if (std::holds_alternative(this->payload)) { - return previous_declaration_note(std::get(this->payload).original); + return previous_declaration_note(std::get(this->payload).original, + "previously declared here", std::get(this->payload).file); } else { @@ -99,7 +100,7 @@ namespace elna::boot }, this->payload); } - std::optional> const_qualifier_error::note() const + std::optional const_qualifier_error::note() const { if (std::holds_alternative(this->payload)) { @@ -175,7 +176,7 @@ namespace elna::boot }, payload); } - std::optional> member_error::note() const + std::optional member_error::note() const { if (std::holds_alternative(this->payload)) { @@ -201,8 +202,9 @@ namespace elna::boot } } - name_analysis_visitor::name_analysis_visitor(symbol_bag bag, const target_info& target) - : bag(std::move(bag)), constant_evaluator(this->bag, target) + name_analysis_visitor::name_analysis_visitor(symbol_bag bag, const target_info& target, + std::filesystem::path module_file) + : bag(std::move(bag)), constant_evaluator(this->bag, target), module_file(std::move(module_file)) { } @@ -295,7 +297,15 @@ namespace elna::boot info->exported = declaration->identifier.exported(); info->position.emplace(declaration->position()); - this->bag.enter(declaration->identifier.name(), info); + info->file = this->module_file; + + if (!this->bag.enter(declaration->identifier.name(), info)) + { + auto original = this->bag.lookup(declaration->identifier.name()); + add_error(declaration->identifier.id().position(), declaration->identifier.name(), + declaration_error::redefinition{ .original = original->position, + .file = this->redefinition_file(original) }); + } } void name_analysis_visitor::visit(pointer_type_expression *expression) @@ -542,17 +552,25 @@ namespace elna::boot this->current_type = type(result_type); } + std::filesystem::path name_analysis_visitor::redefinition_file( + const std::shared_ptr& original) const + { + return original->file != this->module_file ? original->file : std::filesystem::path{}; + } + std::shared_ptr name_analysis_visitor::register_variable(const std::string& name, const bool is_extern, const source_position position) { auto variable_symbol = std::make_shared(this->current_type, is_extern); variable_symbol->position.emplace(position); + variable_symbol->file = this->module_file; if (!this->bag.enter(name, variable_symbol)) { auto original = this->bag.lookup(name); add_error(position, name, - declaration_error::redefinition{ .original = original->position }); + declaration_error::redefinition{ .original = original->position, + .file = this->redefinition_file(original) }); } return variable_symbol; } @@ -631,7 +649,14 @@ namespace elna::boot } info->exported = declaration->identifier.exported(); info->position.emplace(declaration->position()); - this->bag.enter(declaration->identifier.name(), info); + info->file = this->module_file; + if (!this->bag.enter(declaration->identifier.name(), info)) + { + auto original = this->bag.lookup(declaration->identifier.name()); + add_error(declaration->identifier.id().position(), declaration->identifier.name(), + declaration_error::redefinition{ .original = original->position, + .file = this->redefinition_file(original) }); + } } void name_analysis_visitor::visit(procedure_call *call) @@ -666,12 +691,16 @@ namespace elna::boot { this->bag.enter(); auto variable_type = lookup_primitive_type("Int"); - this->bag.enter("count", std::make_shared(variable_type, false)); + auto count_symbol = std::make_shared(variable_type, false); + count_symbol->file = this->module_file; + this->bag.enter("count", count_symbol); variable_type = lookup_primitive_type("Word8"); variable_type = type(std::make_shared(variable_type)); variable_type = type(std::make_shared(variable_type)); - this->bag.enter("parameters", std::make_shared(variable_type, false)); + auto parameters_symbol = std::make_shared(variable_type, false); + parameters_symbol->file = this->module_file; + this->bag.enter("parameters", parameters_symbol); for (statement *const statement : unit->entry_point) { @@ -971,7 +1000,7 @@ namespace elna::boot { add_error(declaration->identifier.id().position(), declaration->identifier.id().name(), - declaration_error::redefinition{ .original = declaration->position() }); + declaration_error::redefinition{ .original = declaration->position(), .file = {} }); } } -- cgit v1.2.3