From f8daedce5c73e02dfb2fc59d75777190185584df Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Wed, 29 Jul 2026 01:16:18 +0200 Subject: Validate cast compatibility during semantic analysis --- include/elna/boot/ast.h | 2 - include/elna/boot/name_analysis.h | 43 +++--------- include/elna/boot/symbol.h | 11 +++ include/elna/boot/type_check.h | 139 ++++++++++++------------------------- include/elna/gcc/elna-diagnostic.h | 1 - include/elna/gcc/elna-tree.h | 1 + 6 files changed, 68 insertions(+), 129 deletions(-) (limited to 'include') diff --git a/include/elna/boot/ast.h b/include/elna/boot/ast.h index 9697d1c..cc5878b 100644 --- a/include/elna/boot/ast.h +++ b/include/elna/boot/ast.h @@ -972,6 +972,4 @@ namespace elna::boot ~unary_expression() override; }; - - const char *print_binary_operator(const binary_operator operation); } diff --git a/include/elna/boot/name_analysis.h b/include/elna/boot/name_analysis.h index 8f53260..626e9f2 100644 --- a/include/elna/boot/name_analysis.h +++ b/include/elna/boot/name_analysis.h @@ -35,27 +35,20 @@ namespace elna::boot class declaration_error : public error { public: - struct undeclared - { - std::string name; - }; - struct local_export - { - std::string name; - }; + enum class kind { undeclared_type, undeclared_trait, undeclared_symbol, local_export }; struct redefinition { - std::string name; std::optional original; }; - using payload_type = std::variant; + using payload_type = std::variant; - declaration_error(const source_position position, payload_type payload); + declaration_error(const source_position position, const std::string& name, payload_type payload); std::string what() const override; std::optional> note() const override; private: + std::string name; payload_type payload; }; @@ -84,46 +77,31 @@ namespace elna::boot public: struct not_found { - std::string name; - type composite; }; struct duplicate { - std::string name; - type aggregate; std::optional original; std::optional base; }; using payload_type = std::variant; - member_error(const source_position position, payload_type payload); + member_error(const source_position position, const std::string& name, + const type& composite, payload_type payload); std::string what() const override; std::optional> note() const override; private: + std::string name; + type composite; payload_type payload; }; - /** - * Trait is not applicable to the given type. - */ - class unsupported_trait_type_error : public error - { - type actual; - std::string trait_name; - - public: - unsupported_trait_type_error(const identifier& trait, type actual); - - std::string what() const override; - }; - /** * Origin of a field in a composite type. */ struct field_origin { - std::optional declaration; + std::optional position; type base_type; }; @@ -139,8 +117,7 @@ namespace elna::boot std::pair> build_procedure( procedure_type_expression& expression); ordered_map build_composite_type(const std::vector& fields, - ordered_map& field_names, - const type& aggregate); + ordered_map& field_names, const type& aggregate); std::shared_ptr register_variable(const std::string& name, const bool is_extern, const source_position position); diff --git a/include/elna/boot/symbol.h b/include/elna/boot/symbol.h index dd3e8ff..01eedb1 100644 --- a/include/elna/boot/symbol.h +++ b/include/elna/boot/symbol.h @@ -576,6 +576,17 @@ namespace elna::boot */ bool is_any_pointer_type(const type& checked); + /** + * Checks whether the given type is a scalar type. + * + * Scalar types are discrete types, floating point numbers, enumerations, + * any pointers. + * + * \param checked The type to check. + * \return Whether the type is a scalar type. + */ + bool is_scalar_type(const type& checked); + /** * If \a range is an array or a slice gives its base type, otherwise * returns an empty type. diff --git a/include/elna/boot/type_check.h b/include/elna/boot/type_check.h index bd32c08..628af06 100644 --- a/include/elna/boot/type_check.h +++ b/include/elna/boot/type_check.h @@ -32,32 +32,49 @@ namespace elna::boot */ class type_mismatch_error : public error { - type expected; - type actual; - public: + struct expected_type + { + type value; + }; + struct return_type + { + std::string identifier; + }; + struct unary + { + unary_operator operation; + }; + struct binary + { + type right; + binary_operator operation; + }; + struct invalid_cast + { + type target; + }; + enum class kind { + record_base, + for_range, + condition, + constant_assignment, + array_index, + non_indexable, + dereference_of_non_pointer + }; + using payload_type = std::variant; + type_mismatch_error(const source_position position, - type expected, type actual); + type actual, payload_type payload); std::string what() const override; - }; - - /** - * Attempted to assign a value whose type contains constant members. - */ - class constant_assignment_error : public error - { - type assignee; - public: - constant_assignment_error(const source_position position, type assignee); - - std::string what() const override; + private: + type actual; + payload_type payload; }; - /** - * Attempted to access a field that does not exist on the given type. - */ /** * Cyclic type declaration. */ @@ -71,42 +88,6 @@ namespace elna::boot std::string what() const override; }; - /** - * Procedure with a return type does not return. - */ - class return_error : public error - { - std::string identifier; - type return_type; - - public: - return_error(const std::string& identifier, const source_position position, - type return_type = type()); - - std::string what() const override; - }; - - /** - * Unexpected kind of a type at specific position. - */ - class type_kind_error : public error - { - public: - enum class kind - { - record_base, - for_loop, - condition - }; - type_kind_error(const source_position position, kind type_kind, const type& actual); - - std::string what() const override; - - private: - kind type_kind; - type actual; - }; - /** * Argument count in a procedure call or array constructor doesn't match * the expected number of parameters or elements. @@ -124,21 +105,23 @@ namespace elna::boot }; /** - * A trait invocation has invalid arguments. + * A trait invocation is invalid. */ class trait_error : public error { public: - /// Wrong number of arguments passed to a trait. struct argument_count { std::size_t expected; std::size_t actual; }; - /// \c \#offset second argument is not a field name. struct offset_not_field_name {}; + struct unsupported_type + { + type actual; + }; - using payload_type = std::variant; + using payload_type = std::variant; trait_error(const source_position position, const std::string& trait_name, payload_type payload); @@ -147,40 +130,7 @@ namespace elna::boot private: std::string trait_name; - payload_type m_payload; - }; - - /** - * A unary operator is applied to an unsupported type. - */ - class unary_operation_error : public error - { - type actual; - unary_operator op; - - static char unary_operator_symbol(unary_operator operation); - - public: - unary_operation_error(const source_position position, type actual, - unary_operator operation); - - std::string what() const override; - }; - - /** - * A binary operator is applied to unsupported types. - */ - class binary_operation_error : public error - { - type left; - type right; - binary_operator op; - - public: - binary_operation_error(const source_position position, - type left, type right, binary_operator operation); - - std::string what() const override; + payload_type payload; }; /** @@ -258,6 +208,9 @@ namespace elna::boot void visit(array_constructor_expression *expression) override; void visit(traits_expression *trait) override; void visit(slicing_expression *expression) override; + void visit(array_access_expression *expression) override; + void visit(dereference_expression *expression) override; + void visit(cast_expression *expression) override; void visit(unary_expression *expression) override; void visit(binary_expression *expression) override; }; diff --git a/include/elna/gcc/elna-diagnostic.h b/include/elna/gcc/elna-diagnostic.h index 2cb30f5..3e0dd51 100644 --- a/include/elna/gcc/elna-diagnostic.h +++ b/include/elna/gcc/elna-diagnostic.h @@ -43,6 +43,5 @@ namespace elna::gcc location_t get_location(const boot::source_position *position); location_t make_range(const boot::source_position& position); - std::string print_type(tree type); void report_errors(const std::deque>& errors); } diff --git a/include/elna/gcc/elna-tree.h b/include/elna/gcc/elna-tree.h index 71cc13b..41f5cc3 100644 --- a/include/elna/gcc/elna-tree.h +++ b/include/elna/gcc/elna-tree.h @@ -63,6 +63,7 @@ namespace elna::gcc tree build_field(location_t location, tree record_type, const std::string& name, tree type); tree find_field_by_name(location_t expression_location, tree type, const std::string& field_name); tree build_static_array_type(tree type, const std::uint64_t size); + tree build_slice(tree slice_type, tree ptr, tree length); tree build_enumeration_type(const std::vector& members); const elna::boot::target_info& get_host_target(); -- cgit v1.2.3