diff options
| author | Eugen Wissner <belka@caraus.de> | 2026-08-01 16:05:51 +0200 |
|---|---|---|
| committer | Eugen Wissner <belka@caraus.de> | 2026-08-01 16:05:51 +0200 |
| commit | 71b3bbb7698b13b42c99a4ca66c27db4a6189ff8 (patch) | |
| tree | 1fc6ed246ecc0cf561f38ad774a4815ba357ea7b /include | |
| parent | 8539c10542a4be1e1127daea60bf1b1e4c37e092 (diff) | |
| download | elna-71b3bbb7698b13b42c99a4ca66c27db4a6189ff8.tar.gz | |
Enforce integral values in slice ranges
Diffstat (limited to 'include')
| -rw-r--r-- | include/elna/boot/result.h | 28 | ||||
| -rw-r--r-- | include/elna/boot/type_check.h | 15 |
2 files changed, 31 insertions, 12 deletions
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<typename T> - T to() const - requires is_integral<T> - { - 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<std::size_t> 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<typename T> static integer_literal from(T initial) requires is_integral<T> @@ -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<integer_literal> 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<expected_type, return_type, unary, binary, invalid_cast, kind>; + 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<integer_literal> *expression) override; }; } |
