diff options
| author | Eugen Wissner <belka@caraus.de> | 2026-08-28 02:39:42 +0200 |
|---|---|---|
| committer | Eugen Wissner <belka@caraus.de> | 2026-08-28 02:39:42 +0200 |
| commit | 8e655a0786aec5e0215e09f2a9629c6f32e34793 (patch) | |
| tree | 0788634cf66fed9c1a1d264b5b8c30da49380559 /boot/name_analysis.cc | |
| parent | 4d4537866690a1ef3d882f5e9a6e01d8220a3650 (diff) | |
| download | elna-8e655a0786aec5e0215e09f2a9629c6f32e34793.tar.gz | |
Reject declarations shadowing imports
Diffstat (limited to 'boot/name_analysis.cc')
| -rw-r--r-- | boot/name_analysis.cc | 55 |
1 files changed, 42 insertions, 13 deletions
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<std::pair<std::string, source_position>> declaration_error::note() const + std::optional<diagnostic_note> declaration_error::note() const { if (std::holds_alternative<redefinition>(this->payload)) { - return previous_declaration_note(std::get<redefinition>(this->payload).original); + return previous_declaration_note(std::get<redefinition>(this->payload).original, + "previously declared here", std::get<redefinition>(this->payload).file); } else { @@ -99,7 +100,7 @@ namespace elna::boot }, this->payload); } - std::optional<std::pair<std::string, source_position>> const_qualifier_error::note() const + std::optional<diagnostic_note> const_qualifier_error::note() const { if (std::holds_alternative<not_initialized>(this->payload)) { @@ -175,7 +176,7 @@ namespace elna::boot }, payload); } - std::optional<std::pair<std::string, source_position>> member_error::note() const + std::optional<diagnostic_note> member_error::note() const { if (std::holds_alternative<duplicate>(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_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<info>& original) const + { + return original->file != this->module_file ? original->file : std::filesystem::path{}; + } + std::shared_ptr<variable_info> name_analysis_visitor::register_variable(const std::string& name, const bool is_extern, const source_position position) { auto variable_symbol = std::make_shared<variable_info>(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<declaration_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_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_info>(variable_type, false)); + auto count_symbol = std::make_shared<variable_info>(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<pointer_type>(variable_type)); variable_type = type(std::make_shared<pointer_type>(variable_type)); - this->bag.enter("parameters", std::make_shared<variable_info>(variable_type, false)); + auto parameters_symbol = std::make_shared<variable_info>(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_error>(declaration->identifier.id().position(), declaration->identifier.id().name(), - declaration_error::redefinition{ .original = declaration->position() }); + declaration_error::redefinition{ .original = declaration->position(), .file = {} }); } } |
