Fixes missing overflow lint for i64 #14269
The `type_overflow` lint, doesn't catch the overflow for `i64` because the overflow happens earlier in the parse phase when the `u64` as biggest possible int gets casted to `i64` , without checking the for overflows. We can't lint in the parse phase, so a refactoring of the `LitInt` type was necessary. The types `LitInt`, `LitUint` and `LitIntUnsuffixed` where merged to one type `LitInt` which stores it's value as `u64`. An additional parameter was added which indicate the signedness of the type and the sign of the value.
This commit is contained in:
parent
795f6ae829
commit
0dc215741b
18 changed files with 142 additions and 99 deletions
|
@ -515,31 +515,13 @@ pub fn integer_lit(s: &str, sd: &SpanHandler, sp: Span) -> ast::Lit_ {
|
|||
debug!("parse_integer_lit: {}", s);
|
||||
|
||||
if s.len() == 1 {
|
||||
return ast::LitIntUnsuffixed((s.char_at(0)).to_digit(10).unwrap() as i64);
|
||||
let n = (s.char_at(0)).to_digit(10).unwrap();
|
||||
return ast::LitInt(n as u64, ast::UnsuffixedIntLit(ast::Sign::new(n)));
|
||||
}
|
||||
|
||||
let mut base = 10;
|
||||
let orig = s;
|
||||
|
||||
#[deriving(Show)]
|
||||
enum Result {
|
||||
Nothing,
|
||||
Signed(ast::IntTy),
|
||||
Unsigned(ast::UintTy)
|
||||
}
|
||||
|
||||
impl Result {
|
||||
fn suffix_len(&self) -> uint {
|
||||
match *self {
|
||||
Nothing => 0,
|
||||
Signed(s) => s.suffix_len(),
|
||||
Unsigned(u) => u.suffix_len()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut ty = Nothing;
|
||||
|
||||
let mut ty = ast::UnsuffixedIntLit(ast::Plus);
|
||||
|
||||
if s.char_at(0) == '0' {
|
||||
match s.char_at(1) {
|
||||
|
@ -556,13 +538,13 @@ pub fn integer_lit(s: &str, sd: &SpanHandler, sp: Span) -> ast::Lit_ {
|
|||
|
||||
let last = s.len() - 1;
|
||||
match s.char_at(last) {
|
||||
'i' => ty = Signed(ast::TyI),
|
||||
'u' => ty = Unsigned(ast::TyU),
|
||||
'i' => ty = ast::SignedIntLit(ast::TyI, ast::Plus),
|
||||
'u' => ty = ast::UnsignedIntLit(ast::TyU),
|
||||
'8' => {
|
||||
if s.len() > 2 {
|
||||
match s.char_at(last - 1) {
|
||||
'i' => ty = Signed(ast::TyI8),
|
||||
'u' => ty = Unsigned(ast::TyU8),
|
||||
'i' => ty = ast::SignedIntLit(ast::TyI8, ast::Plus),
|
||||
'u' => ty = ast::UnsignedIntLit(ast::TyU8),
|
||||
_ => { }
|
||||
}
|
||||
}
|
||||
|
@ -570,8 +552,8 @@ pub fn integer_lit(s: &str, sd: &SpanHandler, sp: Span) -> ast::Lit_ {
|
|||
'6' => {
|
||||
if s.len() > 3 && s.char_at(last - 1) == '1' {
|
||||
match s.char_at(last - 2) {
|
||||
'i' => ty = Signed(ast::TyI16),
|
||||
'u' => ty = Unsigned(ast::TyU16),
|
||||
'i' => ty = ast::SignedIntLit(ast::TyI16, ast::Plus),
|
||||
'u' => ty = ast::UnsignedIntLit(ast::TyU16),
|
||||
_ => { }
|
||||
}
|
||||
}
|
||||
|
@ -579,8 +561,8 @@ pub fn integer_lit(s: &str, sd: &SpanHandler, sp: Span) -> ast::Lit_ {
|
|||
'2' => {
|
||||
if s.len() > 3 && s.char_at(last - 1) == '3' {
|
||||
match s.char_at(last - 2) {
|
||||
'i' => ty = Signed(ast::TyI32),
|
||||
'u' => ty = Unsigned(ast::TyU32),
|
||||
'i' => ty = ast::SignedIntLit(ast::TyI32, ast::Plus),
|
||||
'u' => ty = ast::UnsignedIntLit(ast::TyU32),
|
||||
_ => { }
|
||||
}
|
||||
}
|
||||
|
@ -588,8 +570,8 @@ pub fn integer_lit(s: &str, sd: &SpanHandler, sp: Span) -> ast::Lit_ {
|
|||
'4' => {
|
||||
if s.len() > 3 && s.char_at(last - 1) == '6' {
|
||||
match s.char_at(last - 2) {
|
||||
'i' => ty = Signed(ast::TyI64),
|
||||
'u' => ty = Unsigned(ast::TyU64),
|
||||
'i' => ty = ast::SignedIntLit(ast::TyI64, ast::Plus),
|
||||
'u' => ty = ast::UnsignedIntLit(ast::TyU64),
|
||||
_ => { }
|
||||
}
|
||||
}
|
||||
|
@ -597,21 +579,22 @@ pub fn integer_lit(s: &str, sd: &SpanHandler, sp: Span) -> ast::Lit_ {
|
|||
_ => { }
|
||||
}
|
||||
|
||||
|
||||
s = s.slice_to(s.len() - ty.suffix_len());
|
||||
|
||||
debug!("The suffix is {}, base {}, the new string is {}, the original \
|
||||
string was {}", ty, base, s, orig);
|
||||
|
||||
s = s.slice_to(s.len() - ty.suffix_len());
|
||||
|
||||
let res: u64 = match ::std::num::from_str_radix(s, base) {
|
||||
Some(r) => r,
|
||||
None => { sd.span_err(sp, "int literal is too large"); 0 }
|
||||
};
|
||||
|
||||
// adjust the sign
|
||||
let sign = ast::Sign::new(res);
|
||||
match ty {
|
||||
Nothing => ast::LitIntUnsuffixed(res as i64),
|
||||
Signed(t) => ast::LitInt(res as i64, t),
|
||||
Unsigned(t) => ast::LitUint(res, t)
|
||||
ast::SignedIntLit(t, _) => ast::LitInt(res, ast::SignedIntLit(t, sign)),
|
||||
ast::UnsuffixedIntLit(_) => ast::LitInt(res, ast::UnsuffixedIntLit(sign)),
|
||||
us@ast::UnsignedIntLit(_) => ast::LitInt(res, us)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue