From 8539c10542a4be1e1127daea60bf1b1e4c37e092 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Sat, 1 Aug 2026 09:30:39 +0200 Subject: Fix compile-time negation and array access --- boot/result.cc | 55 +++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 49 insertions(+), 6 deletions(-) (limited to 'boot/result.cc') diff --git a/boot/result.cc b/boot/result.cc index f9f57db..4d4c20f 100644 --- a/boot/result.cc +++ b/boot/result.cc @@ -129,12 +129,14 @@ namespace elna::boot } integer_literal::integer_literal(integer_literal&& that) noexcept + : m_signed(that.is_signed()), m_size(that.size()) { mpz_init(this->raw); mpz_swap(this->raw, that.raw); } integer_literal::integer_literal(const integer_literal& that) + : m_signed(that.is_signed()), m_size(that.size()) { mpz_init(this->raw); mpz_set(this->raw, that.raw); @@ -293,10 +295,7 @@ namespace elna::boot integer_literal& integer_literal::operator=(integer_literal&& that) noexcept { - if (this != &that) - { - mpz_swap(this->raw, that.raw); - } + swap(*this, that); return *this; } @@ -304,11 +303,43 @@ namespace elna::boot { if (this != &that) { - mpz_set(this->raw, that.raw); + integer_literal temp(that); + + swap(*this, temp); } return *this; } + std::optional integer_literal::to_signed() const + { + if (!is_signed()) + { + return std::nullopt; + } + if (is_negative_minimum(sizeof(std::ptrdiff_t) * CHAR_BIT)) + { + return std::numeric_limits::min(); + } + auto [written, rop] = export_to_words(); + + if (written > 1 || rop < 0) + { + return std::nullopt; + } + return mpz_sgn(this->raw) < 0 ? -rop : rop; + } + + std::optional integer_literal::to_unsigned() const + { + if (is_signed()) + { + return std::nullopt; + } + auto [written, rop] = export_to_words(); + + return written > 1 ? std::nullopt : std::make_optional(rop); + } + bool integer_literal::is_signed() const { return this->m_signed; @@ -319,6 +350,13 @@ namespace elna::boot return this->m_size; } + void swap(integer_literal& lhs, integer_literal& rhs) noexcept + { + mpz_swap(lhs.raw, rhs.raw); + std::swap(lhs.m_signed, rhs.m_signed); + std::swap(lhs.m_size, rhs.m_size); + } + std::optional integer_literal::check() && { std::size_t required_bits = mpz_sizeinbase(this->raw, 2); @@ -337,9 +375,14 @@ namespace elna::boot } } + bool integer_literal::is_negative_minimum(const std::size_t bits) const + { + return mpz_sgn(this->raw) < 0 && mpz_scan1(this->raw, 0) == bits - 1; + } + bool integer_literal::is_negative_minimum() const { - return mpz_sgn(this->raw) < 0 && mpz_scan1(this->raw, 0) == bits() - 1; + return is_negative_minimum(bits()); } std::size_t integer_literal::bits() const -- cgit v1.2.3