diff options
| author | Falco Hirschenberger <falco.hirschenberger@gmail.com> | 2014-08-05 09:59:03 +0200 |
|---|---|---|
| committer | Falco Hirschenberger <falco.hirschenberger@gmail.com> | 2014-08-05 09:59:03 +0200 |
| commit | 0dc215741b34236c310e409c437600ba0165c97c (patch) | |
| tree | bfaee6d4c3d1b082fadf859cb106b5e99d458028 /src/libsyntax/parse | |
| parent | 795f6ae829ab1bfd72394a5da9096e2717ec0f62 (diff) | |
| download | rust-0dc215741b34236c310e409c437600ba0165c97c.tar.gz rust-0dc215741b34236c310e409c437600ba0165c97c.zip | |
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.
Diffstat (limited to 'src/libsyntax/parse')
| -rw-r--r-- | src/libsyntax/parse/mod.rs | 57 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 4 |
2 files changed, 22 insertions, 39 deletions
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index a3e169cd511..8f960e37de2 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -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) } } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index de3be4f8f38..18b1d60d4e9 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -34,7 +34,7 @@ use ast::{Ident, NormalFn, Inherited, Item, Item_, ItemStatic}; use ast::{ItemEnum, ItemFn, ItemForeignMod, ItemImpl}; use ast::{ItemMac, ItemMod, ItemStruct, ItemTrait, ItemTy, Lit, Lit_}; use ast::{LitBool, LitChar, LitByte, LitBinary}; -use ast::{LitNil, LitStr, LitUint, Local, LocalLet}; +use ast::{LitNil, LitStr, LitInt, Local, LocalLet}; use ast::{MutImmutable, MutMutable, Mac_, MacInvocTT, Matcher, MatchNonterminal}; use ast::{MatchSeq, MatchTok, Method, MutTy, BiMul, Mutability}; use ast::{NamedField, UnNeg, NoReturn, UnNot, P, Pat, PatEnum}; @@ -1889,7 +1889,7 @@ impl<'a> Parser<'a> { pub fn mk_lit_u32(&mut self, i: u32) -> Gc<Expr> { let span = &self.span; let lv_lit = box(GC) codemap::Spanned { - node: LitUint(i as u64, TyU32), + node: LitInt(i as u64, ast::UnsignedIntLit(TyU32)), span: *span }; |
