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

Reply via email to