From 71b3bbb7698b13b42c99a4ca66c27db4a6189ff8 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Sat, 1 Aug 2026 16:05:51 +0200 Subject: Enforce integral values in slice ranges --- include/elna/boot/result.h | 28 +++++++++++++++++----------- include/elna/boot/type_check.h | 15 ++++++++++++++- 2 files changed, 31 insertions(+), 12 deletions(-) (limited to 'include') diff --git a/include/elna/boot/result.h b/include/elna/boot/result.h index 4c6046d..56884ff 100644 --- a/include/elna/boot/result.h +++ b/include/elna/boot/result.h @@ -268,17 +268,7 @@ namespace elna::boot bool is_signed() const; std::size_t size() const; - - template - T to() const - requires is_integral - { - T result{}; - - mpz_export(&result, nullptr, 1, sizeof(T), 0, 0, this->raw); - - return result; - } + std::string to_string(const std::uint8_t base = 10U) const; /** * Exports the stored value as a host \c std::ptrdiff_t. @@ -294,6 +284,21 @@ namespace elna::boot */ std::optional to_unsigned() const; + /** + * Attempts to narrow this literal's internally stored size to + * \p target_size bytes, in place. + * + * If the current value can be represented within \p target_size bytes + * (given the literal's existing signedness), the internal storage size + * is updated to \p target_size and the function returns \c true. If the + * value would not fit, the literal is left unmodified and \c false is + * returned. + * + * \param target_size Size of the target type in bytes. + * \return Whether the value fits and has been changed. + */ + bool fit_into(const std::size_t target_size); + template static integer_literal from(T initial) requires is_integral @@ -313,6 +318,7 @@ namespace elna::boot mpz_t raw; integer_literal(bool is_signed, std::size_t size); + bool fits_in(const std::size_t bits) const; std::optional check() &&; bool is_negative_minimum(const std::size_t bits) const; bool is_negative_minimum() const; diff --git a/include/elna/boot/type_check.h b/include/elna/boot/type_check.h index 628af06..82f0092 100644 --- a/include/elna/boot/type_check.h +++ b/include/elna/boot/type_check.h @@ -54,6 +54,10 @@ namespace elna::boot { type target; }; + struct integer_literal_overflow + { + integer_literal overflow; + }; enum class kind { record_base, for_range, @@ -63,7 +67,15 @@ namespace elna::boot non_indexable, dereference_of_non_pointer }; - using payload_type = std::variant; + using payload_type = std::variant< + expected_type, + return_type, + unary, + binary, + invalid_cast, + integer_literal_overflow, + kind + >; type_mismatch_error(const source_position position, type actual, payload_type payload); @@ -213,5 +225,6 @@ namespace elna::boot void visit(cast_expression *expression) override; void visit(unary_expression *expression) override; void visit(binary_expression *expression) override; + void visit(literal *expression) override; }; } -- cgit v1.2.3