From b2dee14873402ee3d13d59ae5579593796ea862f Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Wed, 5 Aug 2026 01:03:55 +0200 Subject: Check that constants are initialized --- boot/name_analysis.cc | 62 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 52 insertions(+), 10 deletions(-) (limited to 'boot/name_analysis.cc') diff --git a/boot/name_analysis.cc b/boot/name_analysis.cc index 3667dff..56ea399 100644 --- a/boot/name_analysis.cc +++ b/boot/name_analysis.cc @@ -126,7 +126,8 @@ namespace elna::boot case field_on_type: return "Cannot access field '" + this->name + "' on type '" + this->composite.to_string() + "'"; - break; + default: + __builtin_unreachable(); } } else if constexpr (std::is_same_v) @@ -163,6 +164,23 @@ namespace elna::boot return std::nullopt; } + not_initialized_error::not_initialized_error(const source_position position, std::vector identifiers) + : error(position), identifiers(std::move(identifiers)) + { + } + + std::string not_initialized_error::what() const + { + return "All constants should be initialized"; + } + + std::optional> not_initialized_error::note() const + { + auto position_span = source_position(this->identifiers.front().position().start(), + this->identifiers.back().position().end()); + return std::make_pair(join(this->identifiers), position_span); + } + // Members of a constant aggregate are constant themselves. static type qualify_member_type(const type& element, const type& aggregate) { @@ -177,8 +195,8 @@ namespace elna::boot } } - name_analysis_visitor::name_analysis_visitor(symbol_bag bag) - : bag(std::move(bag)) + name_analysis_visitor::name_analysis_visitor(symbol_bag bag, const target_info& target) + : bag(std::move(bag)), constant_evaluator(this->bag, target) { } @@ -294,14 +312,23 @@ namespace elna::boot void name_analysis_visitor::visit(array_type_expression *expression) { - walking_visitor::visit(expression); + expression->base().accept(this); + auto array_base = this->current_type; - if (this->current_type.get() != nullptr) + if (array_base.get() != nullptr) { add_error(expression->position(), const_qualifier_error::kind::array_position); } - this->current_type = type(std::make_shared(this->current_type, expression->size)); + expression->dimensions().accept(this); + const auto size_constant = this->constant_evaluator.evaluate_index(expression->dimensions()); + + if (!size_constant.has_value()) + { + add_error(expression->position(), + non_constant_expression_error::array_dimensions{ array_base }); + } + this->current_type = type(std::make_shared(array_base, size_constant.value())); } void name_analysis_visitor::visit(slice_type_expression *expression) @@ -437,13 +464,12 @@ namespace elna::boot void name_analysis_visitor::visit(array_constructor_expression *expression) { - expression->m_element_type->accept(this); - auto element_type = this->current_type; + expression->array_type().accept(this); + expression->type_decoration = this->current_type; for (auto *element : expression->elements) { element->accept(this); } - expression->type_decoration = type(std::make_shared(element_type, expression->size)); this->current_type = type(); } @@ -523,20 +549,36 @@ namespace elna::boot { declaration->variable_type().accept(this); auto variable_type = this->current_type; + std::optional computed; + if (declaration->initializer != nullptr) { declaration->initializer->accept(this); this->current_type = variable_type; + computed = this->constant_evaluator.evaluate(*declaration->initializer); + + if (this->bag.is_global() && !computed.has_value()) + { + add_error(declaration->initializer->position(), + non_constant_expression_error::initializer{ extract_identifiers(declaration->identifiers) }); + } + } + else if (resolve_aliases(variable_type).get() != nullptr) + { + auto position_span = source_position(declaration->identifiers.front().id().position().start(), + declaration->identifiers.back().id().position().end()); + add_error(position_span, + extract_identifiers(declaration->identifiers)); } for (const identifier_definition& variable_identifier : declaration->identifiers) { auto variable_symbol = register_variable(variable_identifier.name(), declaration->is_extern, declaration->position()); variable_symbol->exported = variable_identifier.exported(); + variable_symbol->value = computed; } } - void name_analysis_visitor::visit(procedure_declaration *declaration) { std::shared_ptr info; -- cgit v1.2.3