From 60cb8cc43b91ff8a00be45be1106f95f161e9c8d Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Fri, 25 Jun 2021 19:37:11 +0200 Subject: [PATCH] Reject non-pure decimal tuple indexes. Tuple indexes should be pure decimal integer literals. But the parser just sees an integer literal. Fix this by introducing a new type hint CORETYPE_PURE_DECIMAL. This doesn't conflict with any existing type hints since a pure decimal doesn't have a type suffix. Introduce a new method is_pure_decimal that the parser can use in parse_tuple_index_expr. get_type_hint will return CORETYPE_UNKNOWN for pure decimals. parse_decimal_int_or_float will check whether there are no execissive leading zeros. parse_in_decimal checks the literal doesn't contain any underscores. Add two testcases. bad_tuple_index.rs with all variants of integer literals which aren't pure decimals. And tuple_index.rs with various correct tuple indexes. Resolves: https://github.com/Rust-GCC/gccrs/issues/511 --- gcc/rust/lex/rust-lex.cc | 33 ++++++---- gcc/rust/lex/rust-lex.h | 2 +- gcc/rust/lex/rust-token.cc | 2 + gcc/rust/lex/rust-token.h | 11 +++- gcc/rust/parse/rust-parse-impl.h | 6 ++ gcc/testsuite/rust/compile/bad_tuple_index.rs | 66 +++++++++++++++++++ .../rust/compile/torture/tuple_index.rs | 32 +++++++++ 7 files changed, 139 insertions(+), 13 deletions(-) create mode 100644 gcc/testsuite/rust/compile/bad_tuple_index.rs create mode 100644 gcc/testsuite/rust/compile/torture/tuple_index.rs diff --git a/gcc/rust/lex/rust-lex.cc b/gcc/rust/lex/rust-lex.cc index b320401e3bb..d1384168731 100644 --- a/gcc/rust/lex/rust-lex.cc +++ b/gcc/rust/lex/rust-lex.cc @@ -942,23 +942,26 @@ Lexer::parse_in_exponent_part () } // parse another decimal number for exponent - auto str_length_pair = parse_in_decimal (); - str += str_length_pair.first; - additional_length_offset += str_length_pair.second; + auto str_length = parse_in_decimal (); + str += std::get<0> (str_length); + additional_length_offset += std::get<1> (str_length); } return std::make_pair (str, additional_length_offset); } // Parses a decimal integer. -std::pair +std::tuple Lexer::parse_in_decimal () { + /* A pure decimal contains only digits. */ + bool pure_decimal = true; int additional_length_offset = 0; std::string str; while (ISDIGIT (current_char) || current_char == '_') { if (current_char == '_') { + pure_decimal = false; // don't add _ to number skip_input (); current_char = peek_input (); @@ -974,7 +977,7 @@ Lexer::parse_in_decimal () skip_input (); current_char = peek_input (); } - return std::make_pair (str, additional_length_offset); + return std::make_tuple (str, additional_length_offset, pure_decimal); } /* Parses escapes (and string continues) in "byte" strings and characters. Does @@ -1842,13 +1845,14 @@ Lexer::parse_decimal_int_or_float (Location loc) str += current_char; int length = 1; + bool first_zero = current_char == '0'; current_char = peek_input (); // parse initial decimal integer (or first integer part of float) literal - auto initial_decimal_pair = parse_in_decimal (); - str += initial_decimal_pair.first; - length += initial_decimal_pair.second; + auto initial_decimal = parse_in_decimal (); + str += std::get<0> (initial_decimal); + length += std::get<1> (initial_decimal); // detect float literal if (current_char == '.' && is_float_digit (peek_input (1))) @@ -1862,9 +1866,9 @@ Lexer::parse_decimal_int_or_float (Location loc) length++; // parse another decimal number for float - auto second_decimal_pair = parse_in_decimal (); - str += second_decimal_pair.first; - length += second_decimal_pair.second; + auto second_decimal = parse_in_decimal (); + str += std::get<0> (second_decimal); + length += std::get<1> (second_decimal); // parse in exponent part if it exists auto exponent_pair = parse_in_exponent_part (); @@ -1947,6 +1951,13 @@ Lexer::parse_decimal_int_or_float (Location loc) // parse in type suffix if it exists auto type_suffix_pair = parse_in_type_suffix (); PrimitiveCoreType type_hint = type_suffix_pair.first; + /* A "real" pure decimal doesn't have a suffix and no zero prefix. */ + if (type_hint == CORETYPE_UNKNOWN) + { + bool pure_decimal = std::get<2> (initial_decimal); + if (pure_decimal && (!first_zero || str.size () == 1)) + type_hint = CORETYPE_PURE_DECIMAL; + } length += type_suffix_pair.second; current_column += length; diff --git a/gcc/rust/lex/rust-lex.h b/gcc/rust/lex/rust-lex.h index ba37c63416d..902745fa1d5 100644 --- a/gcc/rust/lex/rust-lex.h +++ b/gcc/rust/lex/rust-lex.h @@ -71,7 +71,7 @@ private: // Builds a token from the input queue. TokenPtr build_token (); - std::pair parse_in_decimal (); + std::tuple parse_in_decimal (); std::pair parse_in_exponent_part (); std::pair parse_in_type_suffix (); std::tuple parse_escape (char opening_char); diff --git a/gcc/rust/lex/rust-token.cc b/gcc/rust/lex/rust-token.cc index 7b5a305bbea..317416cb349 100644 --- a/gcc/rust/lex/rust-token.cc +++ b/gcc/rust/lex/rust-token.cc @@ -99,6 +99,8 @@ get_type_hint_string (PrimitiveCoreType type) return "u64"; case CORETYPE_U128: return "u128"; + case CORETYPE_PURE_DECIMAL: + return "pure_decimal"; case CORETYPE_UNKNOWN: default: return "unknown"; diff --git a/gcc/rust/lex/rust-token.h b/gcc/rust/lex/rust-token.h index e8d5519e22a..771910119b7 100644 --- a/gcc/rust/lex/rust-token.h +++ b/gcc/rust/lex/rust-token.h @@ -57,6 +57,9 @@ enum PrimitiveCoreType CORETYPE_U32, CORETYPE_U64, CORETYPE_U128, + // Pure decimals are used for tuple index. + // Also means there is no type hint. + CORETYPE_PURE_DECIMAL, // arch-dependent pointer sizes CORETYPE_ISIZE = CORETYPE_INT, CORETYPE_USIZE = CORETYPE_UINT @@ -391,7 +394,10 @@ return *str; }*/ // Gets token's type hint info. - PrimitiveCoreType get_type_hint () const { return type_hint; } + PrimitiveCoreType get_type_hint () const + { + return type_hint == CORETYPE_PURE_DECIMAL ? CORETYPE_UNKNOWN : type_hint; + } // diagnostics (error reporting) const char *get_token_description () const @@ -435,6 +441,9 @@ return *str; { return is_literal () || token_id == IDENTIFIER || token_id == LIFETIME; } + + // Returns whether the token is a pure decimal int literal + bool is_pure_decimal () const { return type_hint == CORETYPE_PURE_DECIMAL; } }; } // namespace Rust diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 9a28f6cdb66..014beaf9e9c 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -14083,6 +14083,12 @@ Parser::parse_tuple_index_expr ( std::string index = index_tok->get_str (); // convert to integer + if (!index_tok->is_pure_decimal ()) + { + Error error (index_tok->get_locus (), + "tuple index should be a pure decimal literal"); + add_error (std::move (error)); + } int index_int = atoi (index.c_str ()); Location locus = tuple_expr->get_locus_slow (); diff --git a/gcc/testsuite/rust/compile/bad_tuple_index.rs b/gcc/testsuite/rust/compile/bad_tuple_index.rs new file mode 100644 index 00000000000..c3bd1e91d10 --- /dev/null +++ b/gcc/testsuite/rust/compile/bad_tuple_index.rs @@ -0,0 +1,66 @@ +fn main() +{ + // tuples + let z = (); + + let o = (0,); + /* Binary, Octal and Hex literals are invalid. */ + let _fb = o.0b0; // { dg-error "tuple index should be a pure decimal literal" } + let _fo = o.0o0; // { dg-error "tuple index should be a pure decimal literal" } + let _fh = o.0x0; // { dg-error "tuple index should be a pure decimal literal" } + + /* No underscores. */ + let _fua = o.0_; // { dg-error "tuple index should be a pure decimal literal" } + + /* Suffix is not allowed. */ + let _fu8 = o.0u8; // { dg-error "tuple index should be a pure decimal literal" } + let _fi8 = o.0i8; // { dg-error "tuple index should be a pure decimal literal" } + let _fu16 = o.0u16; // { dg-error "tuple index should be a pure decimal literal" } + let _fi16 = o.0i16; // { dg-error "tuple index should be a pure decimal literal" } + let _fu32 = o.0u32; // { dg-error "tuple index should be a pure decimal literal" } + let _fi32 = o.0i32; // { dg-error "tuple index should be a pure decimal literal" } + let _fu64 = o.0u64; // { dg-error "tuple index should be a pure decimal literal" } + let _fi64 = o.0i64; // { dg-error "tuple index should be a pure decimal literal" } + let _fu128 = o.0u128; // { dg-error "tuple index should be a pure decimal literal" } + let _fi128 = o.0i128; // { dg-error "tuple index should be a pure decimal literal" } + let _fusize = o.0usize; // { dg-error "tuple index should be a pure decimal literal" } + let _fisize = o.0isize; // { dg-error "tuple index should be a pure decimal literal" } + + let t = (0,1); + /* No extra zero prefix. */ + let _s = t.01; // { dg-error "tuple index should be a pure decimal literal" } + + let m = (0,1,2,3,4,5,6,7,8,9,10); + /* No extra zero prefix. */ + let _l = m.010; // { dg-error "tuple index should be a pure decimal literal" } + + /* No underscores. */ + let _lu = m.1_0; // { dg-error "tuple index should be a pure decimal literal" } + + // tuple structs + struct E(); + let _e = E(); + + struct O(i32); + let so = O(0); + /* No leading zeros, no underscores. */ + let _sf = so.0_0; // { dg-error "tuple index should be a pure decimal literal" } + /* Binary, Octal and Hex literals are invalid. */ + let _sb = so.0b0; // { dg-error "tuple index should be a pure decimal literal" } + let _so = so.0o0; // { dg-error "tuple index should be a pure decimal literal" } + let _sh = so.0x0; // { dg-error "tuple index should be a pure decimal literal" } + + struct T(i32,i32); + let st = T(0,1); + /* Suffix is not allowed. */ + let _stfu32 = st.1u32; // { dg-error "tuple index should be a pure decimal literal" } + let _stfi32 = st.1i32; // { dg-error "tuple index should be a pure decimal literal" } + + struct M(i32,i32,i32,i32,i32,i32,i32,i32,i32,i32,i32); + let sm = M(0,1,2,3,4,5,6,7,8,9,10); + /* No underscores. */ + let _sl2 = sm.1_0; // { dg-error "tuple index should be a pure decimal literal" } + let _sl3 = sm.10_; // { dg-error "tuple index should be a pure decimal literal" } + + z +} diff --git a/gcc/testsuite/rust/compile/torture/tuple_index.rs b/gcc/testsuite/rust/compile/torture/tuple_index.rs new file mode 100644 index 00000000000..f904fae9b5b --- /dev/null +++ b/gcc/testsuite/rust/compile/torture/tuple_index.rs @@ -0,0 +1,32 @@ +fn main() +{ + // tuples + let z = (); + + let o = (0,); + let _f = o.0; + + let t = (0,1); + let _s = t.1; + + let m = (0,1,2,3,4,5,6,7,8,9,10); + let _l = m.10; + + // tuple structs + struct E(); + let _e = E(); + + struct O(i32); + let so = O(0); + let _sf = so.0; + + struct T(i32,i32); + let st = T(0,1); + let _fs = st.1; + + struct M(i32,i32,i32,i32,i32,i32,i32,i32,i32,i32,i32); + let sm = M(0,1,2,3,4,5,6,7,8,9,10); + let _sl = sm.10; + + z +} -- 2.32.0