Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 15 additions & 15 deletions gcc/rust/lex/rust-lex.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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 ();
Expand All @@ -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);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mpz_set_str return value unchecked return -1 on invalid input.
Digits are already validated by is_digit_func
assert checking this value would be dfensive.

Suggested change
mpz_set_str (dec_num, raw_str.c_str (), base);
int ret = mpz_set_str (dec_num, raw_str.c_str (), base);
gcc_assert (ret == 0);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it should be fine since it's validated by is_digit_func. That said, it might still be a good idea, I'll add it.

char *s = mpz_get_str (NULL, 10, dec_num);
std::string dec_str = s;
free (s);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GMP may use a custom memory allocator, so free() isn't guaranteed to match.
take a look https://gmplib.org/manual/Converting-Integers

Suggested change
free (s);
void (*freefunc)(void *, size_t);
mp_get_memory_functions (NULL, NULL, &freefunc);
freefunc (s, strlen (s) + 1);

https://gmplib.org/manual/Custom-Allocation

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This document covers general usage. Looking at the GMP usages across the GCC source, they all call free() directly

mpz_clear (dec_num);

// parse in type suffix if it exists
auto type_suffix_pair = parse_in_type_suffix ();
Expand All @@ -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
{
Expand Down
3 changes: 1 addition & 2 deletions gcc/rust/lex/rust-lex.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,8 +154,7 @@ class Lexer

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
Expand Down
24 changes: 24 additions & 0 deletions gcc/testsuite/rust/execute/non_decimal_128_saturation.rs
Original file line number Diff line number Diff line change
@@ -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
}
Loading