From: Enes Cevik <[email protected]>
This patch replaces std::strtol with GNU MP (GMP) for arbitrary-precision
parsing to properly support 128-bit literals.
Additionally, it refactors the lexer by removing the redundant
`existent_str` parameter from `parse_non_decimal_int_literal`. The base
is now passed directly, and the parsed digits are collected internally,
making the previous prefix-passing logic ("0x", "0b", "0o") obsolete
and ensuring cleaner compatibility with mpz_set_str.
gcc/rust/ChangeLog:
* lex/rust-lex.cc (Lexer::parse_non_decimal_int_literal): Use GMP
for base conversion to support 128-bit literals. Remove existent_str
parameter.
(Lexer::parse_non_decimal_int_literals): Remove prefix string
initialization and update function calls.
* lex/rust-lex.h (Lexer::parse_non_decimal_int_literal): Update
function signature to remove existent_str.
gcc/testsuite/ChangeLog:
* rust/execute/non_decimal_128_saturation.rs: New test.
Signed-off-by: Enes Cevik <[email protected]>
---
gcc/rust/lex/rust-lex.cc | 30 +++++++++----------
gcc/rust/lex/rust-lex.h | 3 +-
.../execute/non_decimal_128_saturation.rs | 24 +++++++++++++++
3 files changed, 40 insertions(+), 17 deletions(-)
create mode 100644 gcc/testsuite/rust/execute/non_decimal_128_saturation.rs
diff --git a/gcc/rust/lex/rust-lex.cc b/gcc/rust/lex/rust-lex.cc
index 599358e44b3..681219160c5 100644
--- a/gcc/rust/lex/rust-lex.cc
+++ b/gcc/rust/lex/rust-lex.cc
@@ -2239,8 +2239,10 @@ Lexer::parse_raw_string (location_t loc, int
initial_hash_count)
template <typename IsDigitFunc>
TokenPtr
Lexer::parse_non_decimal_int_literal (location_t loc, IsDigitFunc
is_digit_func,
- std::string existent_str, int base)
+ int base)
{
+ std::string raw_str;
+
int length = 1;
skip_input ();
@@ -2265,15 +2267,19 @@ Lexer::parse_non_decimal_int_literal (location_t loc,
IsDigitFunc is_digit_func,
length++;
// add raw numbers
- existent_str += current_char;
+ raw_str += current_char;
skip_input ();
current_char = peek_input ();
}
// convert value to decimal representation
- long dec_num = std::strtol (existent_str.c_str (), nullptr, base);
-
- existent_str = std::to_string (dec_num);
+ mpz_t dec_num;
+ mpz_init (dec_num);
+ mpz_set_str (dec_num, raw_str.c_str (), base);
+ char *s = mpz_get_str (NULL, 10, dec_num);
+ std::string dec_str = s;
+ free (s);
+ mpz_clear (dec_num);
// parse in type suffix if it exists
auto type_suffix_pair = parse_in_type_suffix ();
@@ -2297,35 +2303,29 @@ Lexer::parse_non_decimal_int_literal (location_t loc,
IsDigitFunc is_digit_func,
loc += length - 1;
- return Token::make_int (loc, std::move (existent_str), type_hint);
+ return Token::make_int (loc, std::move (dec_str), type_hint);
}
// Parses a hex, binary or octal int literal.
TokenPtr
Lexer::parse_non_decimal_int_literals (location_t loc)
{
- std::string str;
- str.reserve (16); // some sensible default
- str += current_char;
-
current_char = peek_input ();
if (current_char == 'x')
{
// hex (integer only)
- return parse_non_decimal_int_literal (loc, is_x_digit, str + "x", 16);
+ return parse_non_decimal_int_literal (loc, is_x_digit, 16);
}
else if (current_char == 'o')
{
// octal (integer only)
- return parse_non_decimal_int_literal (loc, is_octal_digit,
- std::move (str), 8);
+ return parse_non_decimal_int_literal (loc, is_octal_digit, 8);
}
else if (current_char == 'b')
{
// binary (integer only)
- return parse_non_decimal_int_literal (loc, is_bin_digit, std::move (str),
- 2);
+ return parse_non_decimal_int_literal (loc, is_bin_digit, 2);
}
else
{
diff --git a/gcc/rust/lex/rust-lex.h b/gcc/rust/lex/rust-lex.h
index 31ba0921742..b14dffb2c9a 100644
--- a/gcc/rust/lex/rust-lex.h
+++ b/gcc/rust/lex/rust-lex.h
@@ -154,8 +154,7 @@ private:
template <typename IsDigitFunc>
TokenPtr parse_non_decimal_int_literal (location_t loc,
- IsDigitFunc is_digit_func,
- std::string existent_str, int base);
+ IsDigitFunc is_digit_func, int base);
public:
// Construct lexer with input file and filename provided
diff --git a/gcc/testsuite/rust/execute/non_decimal_128_saturation.rs
b/gcc/testsuite/rust/execute/non_decimal_128_saturation.rs
new file mode 100644
index 00000000000..5020d3cf432
--- /dev/null
+++ b/gcc/testsuite/rust/execute/non_decimal_128_saturation.rs
@@ -0,0 +1,24 @@
+// { dg-do run }
+// { dg-require-effective-target lp64 }
+// { dg-options "-O0" }
+#![feature(no_core)]
+#![no_core]
+
+fn main() -> i32 {
+ let hex_val: u128 = 0x1_0000_0000_0000_0000_u128;
+ if (hex_val >> 64) as u8 != 1 {
+ return 1;
+ }
+
+ let bin_val: u128 =
+
0b1_00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000_u128;
+ if (bin_val >> 64) as u8 != 1 {
+ return 1;
+ }
+
+ let oct_val: u128 = 0o2_000_000_000_000_000_000_000_u128;
+ if (oct_val >> 64) as u8 != 1 {
+ return 1;
+ }
+ 0
+}
--
2.50.1