aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Wielaard <mark@klomp.org>2021-06-25 19:37:11 +0200
committerMark Wielaard <mark@klomp.org>2021-06-25 21:50:37 +0200
commit60cb8cc43b91ff8a00be45be1106f95f161e9c8d (patch)
treebd85ffbf6bf29ece4c4409e39d24fba3fb37748f
parent99bc27d278359be9aec5597504807a6456a88a6c (diff)
downloadgcc-60cb8cc43b91ff8a00be45be1106f95f161e9c8d.zip
gcc-60cb8cc43b91ff8a00be45be1106f95f161e9c8d.tar.gz
gcc-60cb8cc43b91ff8a00be45be1106f95f161e9c8d.tar.bz2
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
-rw-r--r--gcc/rust/lex/rust-lex.cc33
-rw-r--r--gcc/rust/lex/rust-lex.h2
-rw-r--r--gcc/rust/lex/rust-token.cc2
-rw-r--r--gcc/rust/lex/rust-token.h11
-rw-r--r--gcc/rust/parse/rust-parse-impl.h6
-rw-r--r--gcc/testsuite/rust/compile/bad_tuple_index.rs66
-rw-r--r--gcc/testsuite/rust/compile/torture/tuple_index.rs32
7 files changed, 139 insertions, 13 deletions
diff --git a/gcc/rust/lex/rust-lex.cc b/gcc/rust/lex/rust-lex.cc
index b320401..d138416 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::string, int>
+std::tuple<std::string, int, bool>
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 ba37c63..902745f 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<std::string, int> parse_in_decimal ();
+ std::tuple<std::string, int, bool> parse_in_decimal ();
std::pair<std::string, int> parse_in_exponent_part ();
std::pair<PrimitiveCoreType, int> parse_in_type_suffix ();
std::tuple<char, int, bool> parse_escape (char opening_char);
diff --git a/gcc/rust/lex/rust-token.cc b/gcc/rust/lex/rust-token.cc
index 7b5a305..317416c 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 e8d5519..7719101 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 9a28f6c..014beaf 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -14083,6 +14083,12 @@ Parser<ManagedTokenSource>::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 0000000..c3bd1e9
--- /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 0000000..f904fae
--- /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
+}