Skip to content

Commit 0dc2157

Browse files
Fixes missing overflow lint for i64 rust-lang#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.
1 parent 795f6ae commit 0dc2157

File tree

18 files changed

+142
-99
lines changed

18 files changed

+142
-99
lines changed

src/libfourcc/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
124124
(val << 8) | (byte as u32)
125125
};
126126
}
127-
let e = cx.expr_lit(sp, ast::LitUint(val as u64, ast::TyU32));
127+
let e = cx.expr_lit(sp, ast::LitInt(val as u64, ast::UnsignedIntLit(ast::TyU32)));
128128
MacExpr::new(e)
129129
}
130130

src/librustc/lint/builtin.rs

+21-14
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ impl LintPass for TypeLimits {
135135
match expr.node {
136136
ast::ExprLit(lit) => {
137137
match lit.node {
138-
ast::LitUint(..) => {
138+
ast::LitInt(_, ast::UnsignedIntLit(_)) => {
139139
cx.span_lint(UNSIGNED_NEGATE, e.span,
140140
"negation of unsigned int literal may \
141141
be unintentional");
@@ -177,15 +177,25 @@ impl LintPass for TypeLimits {
177177
} else { t };
178178
let (min, max) = int_ty_range(int_type);
179179
let mut lit_val: i64 = match lit.node {
180-
ast::LitInt(v, _) => v,
181-
ast::LitUint(v, _) => v as i64,
182-
ast::LitIntUnsuffixed(v) => v,
180+
ast::LitInt(v, ast::SignedIntLit(_, ast::Plus)) |
181+
ast::LitInt(v, ast::UnsuffixedIntLit(ast::Plus)) => {
182+
if v > i64::MAX as u64{
183+
cx.span_lint(TYPE_OVERFLOW, e.span,
184+
"literal out of range for its type");
185+
return;
186+
}
187+
v as i64
188+
}
189+
ast::LitInt(v, ast::SignedIntLit(_, ast::Minus)) |
190+
ast::LitInt(v, ast::UnsuffixedIntLit(ast::Minus)) => {
191+
-(v as i64)
192+
}
183193
_ => fail!()
184194
};
185195
if self.negated_expr_id == e.id {
186196
lit_val *= -1;
187197
}
188-
if lit_val < min || lit_val > max {
198+
if lit_val < min || lit_val > max {
189199
cx.span_lint(TYPE_OVERFLOW, e.span,
190200
"literal out of range for its type");
191201
}
@@ -197,9 +207,7 @@ impl LintPass for TypeLimits {
197207
let (min, max) = uint_ty_range(uint_type);
198208
let lit_val: u64 = match lit.node {
199209
ast::LitByte(_v) => return, // _v is u8, within range by definition
200-
ast::LitInt(v, _) => v as u64,
201-
ast::LitUint(v, _) => v,
202-
ast::LitIntUnsuffixed(v) => v as u64,
210+
ast::LitInt(v, _) => v,
203211
_ => fail!()
204212
};
205213
if lit_val < min || lit_val > max {
@@ -294,9 +302,10 @@ impl LintPass for TypeLimits {
294302
let (min, max) = int_ty_range(int_ty);
295303
let lit_val: i64 = match lit.node {
296304
ast::ExprLit(li) => match li.node {
297-
ast::LitInt(v, _) => v,
298-
ast::LitUint(v, _) => v as i64,
299-
ast::LitIntUnsuffixed(v) => v,
305+
ast::LitInt(v, ast::SignedIntLit(_, ast::Plus)) |
306+
ast::LitInt(v, ast::UnsuffixedIntLit(ast::Plus)) => v as i64,
307+
ast::LitInt(v, ast::SignedIntLit(_, ast::Minus)) |
308+
ast::LitInt(v, ast::UnsuffixedIntLit(ast::Minus)) => -(v as i64),
300309
_ => return true
301310
},
302311
_ => fail!()
@@ -307,9 +316,7 @@ impl LintPass for TypeLimits {
307316
let (min, max): (u64, u64) = uint_ty_range(uint_ty);
308317
let lit_val: u64 = match lit.node {
309318
ast::ExprLit(li) => match li.node {
310-
ast::LitInt(v, _) => v as u64,
311-
ast::LitUint(v, _) => v,
312-
ast::LitIntUnsuffixed(v) => v as u64,
319+
ast::LitInt(v, _) => v,
313320
_ => return true
314321
},
315322
_ => fail!()

src/librustc/middle/const_eval.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -560,10 +560,13 @@ pub fn lit_to_const(lit: &Lit) -> const_val {
560560
}
561561
LitByte(n) => const_uint(n as u64),
562562
LitChar(n) => const_uint(n as u64),
563-
LitInt(n, _) => const_int(n),
564-
LitUint(n, _) => const_uint(n),
565-
LitIntUnsuffixed(n) => const_int(n),
566-
LitFloat(ref n, _) | LitFloatUnsuffixed(ref n) => {
563+
LitInt(n, ast::SignedIntLit(_, ast::Plus)) |
564+
LitInt(n, ast::UnsuffixedIntLit(ast::Plus)) => const_int(n as i64),
565+
LitInt(n, ast::SignedIntLit(_, ast::Minus)) |
566+
LitInt(n, ast::UnsuffixedIntLit(ast::Minus)) => const_int(-(n as i64)),
567+
LitInt(n, ast::UnsignedIntLit(_)) => const_uint(n),
568+
LitFloat(ref n, _) |
569+
LitFloatUnsuffixed(ref n) => {
567570
const_float(from_str::<f64>(n.get()).unwrap() as f64)
568571
}
569572
LitNil => const_nil,

src/librustc/middle/trans/consts.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,13 @@ pub fn const_lit(cx: &CrateContext, e: &ast::Expr, lit: ast::Lit)
4747
match lit.node {
4848
ast::LitByte(b) => C_integral(Type::uint_from_ty(cx, ast::TyU8), b as u64, false),
4949
ast::LitChar(i) => C_integral(Type::char(cx), i as u64, false),
50-
ast::LitInt(i, t) => C_integral(Type::int_from_ty(cx, t), i as u64, true),
51-
ast::LitUint(u, t) => C_integral(Type::uint_from_ty(cx, t), u, false),
52-
ast::LitIntUnsuffixed(i) => {
50+
ast::LitInt(i, ast::SignedIntLit(t, _)) => {
51+
C_integral(Type::int_from_ty(cx, t), i, true)
52+
}
53+
ast::LitInt(u, ast::UnsignedIntLit(t)) => {
54+
C_integral(Type::uint_from_ty(cx, t), u, false)
55+
}
56+
ast::LitInt(i, ast::UnsuffixedIntLit(_)) => {
5357
let lit_int_ty = ty::node_id_to_type(cx.tcx(), e.id);
5458
match ty::get(lit_int_ty).sty {
5559
ty::ty_int(t) => {

src/librustc/middle/typeck/check/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -2057,9 +2057,9 @@ fn check_lit(fcx: &FnCtxt,
20572057
}
20582058
ast::LitByte(_) => ty::mk_u8(),
20592059
ast::LitChar(_) => ty::mk_char(),
2060-
ast::LitInt(_, t) => ty::mk_mach_int(t),
2061-
ast::LitUint(_, t) => ty::mk_mach_uint(t),
2062-
ast::LitIntUnsuffixed(_) => {
2060+
ast::LitInt(_, ast::SignedIntLit(t, _)) => ty::mk_mach_int(t),
2061+
ast::LitInt(_, ast::UnsignedIntLit(t)) => ty::mk_mach_uint(t),
2062+
ast::LitInt(_, ast::UnsuffixedIntLit(_)) => {
20632063
let opt_ty = expected.map_to_option(fcx, |sty| {
20642064
match *sty {
20652065
ty::ty_int(i) => Some(ty::mk_mach_int(i)),

src/librustdoc/clean/mod.rs

-2
Original file line numberDiff line numberDiff line change
@@ -1947,8 +1947,6 @@ fn lit_to_string(lit: &ast::Lit) -> String {
19471947
},
19481948
ast::LitChar(c) => format!("'{}'", c),
19491949
ast::LitInt(i, _t) => i.to_string(),
1950-
ast::LitUint(u, _t) => u.to_string(),
1951-
ast::LitIntUnsuffixed(i) => i.to_string(),
19521950
ast::LitFloat(ref f, _t) => f.get().to_string(),
19531951
ast::LitFloatUnsuffixed(ref f) => f.get().to_string(),
19541952
ast::LitBool(b) => b.to_string(),

src/libsyntax/ast.rs

+35-3
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use parse::token::{InternedString, str_to_ident};
1818
use parse::token;
1919

2020
use std::fmt;
21+
use std::num::Zero;
2122
use std::fmt::Show;
2223
use std::option::Option;
2324
use std::rc::Rc;
@@ -656,15 +657,46 @@ pub enum StrStyle {
656657

657658
pub type Lit = Spanned<Lit_>;
658659

660+
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
661+
pub enum Sign {
662+
Minus,
663+
Plus
664+
}
665+
666+
impl<T: PartialOrd+Zero> Sign {
667+
pub fn new(n: T) -> Sign {
668+
if n < Zero::zero() {
669+
Minus
670+
} else {
671+
Plus
672+
}
673+
}
674+
}
675+
676+
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
677+
pub enum LitIntType {
678+
SignedIntLit(IntTy, Sign),
679+
UnsignedIntLit(UintTy),
680+
UnsuffixedIntLit(Sign)
681+
}
682+
683+
impl LitIntType {
684+
pub fn suffix_len(&self) -> uint {
685+
match *self {
686+
UnsuffixedIntLit(_) => 0,
687+
SignedIntLit(s, _) => s.suffix_len(),
688+
UnsignedIntLit(u) => u.suffix_len()
689+
}
690+
}
691+
}
692+
659693
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
660694
pub enum Lit_ {
661695
LitStr(InternedString, StrStyle),
662696
LitBinary(Rc<Vec<u8> >),
663697
LitByte(u8),
664698
LitChar(char),
665-
LitInt(i64, IntTy),
666-
LitUint(u64, UintTy),
667-
LitIntUnsuffixed(i64),
699+
LitInt(u64, LitIntType),
668700
LitFloat(InternedString, FloatTy),
669701
LitFloatUnsuffixed(InternedString),
670702
LitNil,

src/libsyntax/ext/build.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -626,13 +626,13 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
626626
self.expr(sp, ast::ExprLit(box(GC) respan(sp, lit)))
627627
}
628628
fn expr_uint(&self, span: Span, i: uint) -> Gc<ast::Expr> {
629-
self.expr_lit(span, ast::LitUint(i as u64, ast::TyU))
629+
self.expr_lit(span, ast::LitInt(i as u64, ast::UnsignedIntLit(ast::TyU)))
630630
}
631631
fn expr_int(&self, sp: Span, i: int) -> Gc<ast::Expr> {
632-
self.expr_lit(sp, ast::LitInt(i as i64, ast::TyI))
632+
self.expr_lit(sp, ast::LitInt(i as u64, ast::SignedIntLit(ast::TyI, ast::Sign::new(i))))
633633
}
634634
fn expr_u8(&self, sp: Span, u: u8) -> Gc<ast::Expr> {
635-
self.expr_lit(sp, ast::LitUint(u as u64, ast::TyU8))
635+
self.expr_lit(sp, ast::LitInt(u as u64, ast::UnsignedIntLit(ast::TyU8)))
636636
}
637637
fn expr_bool(&self, sp: Span, value: bool) -> Gc<ast::Expr> {
638638
self.expr_lit(sp, ast::LitBool(value))

src/libsyntax/ext/bytes.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
4747
}
4848

4949
// u8 literal, push to vector expression
50-
ast::LitUint(v, ast::TyU8) => {
50+
ast::LitInt(v, ast::UnsignedIntLit(ast::TyU8)) => {
5151
if v > 0xFF {
5252
cx.span_err(expr.span, "too large u8 literal in bytes!");
5353
err = true;
@@ -57,13 +57,14 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
5757
}
5858

5959
// integer literal, push to vector expression
60-
ast::LitIntUnsuffixed(v) => {
60+
ast::LitInt(_, ast::UnsuffixedIntLit(ast::Minus)) => {
61+
cx.span_err(expr.span, "negative integer literal in bytes!");
62+
err = true;
63+
}
64+
ast::LitInt(v, ast::UnsuffixedIntLit(ast::Plus)) => {
6165
if v > 0xFF {
6266
cx.span_err(expr.span, "too large integer literal in bytes!");
6367
err = true;
64-
} else if v < 0 {
65-
cx.span_err(expr.span, "negative integer literal in bytes!");
66-
err = true;
6768
} else {
6869
bytes.push(cx.expr_u8(expr.span, v as u8));
6970
}

src/libsyntax/ext/concat.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,14 @@ pub fn expand_syntax_ext(cx: &mut base::ExtCtxt,
3737
ast::LitChar(c) => {
3838
accumulator.push_char(c);
3939
}
40-
ast::LitInt(i, _) | ast::LitIntUnsuffixed(i) => {
40+
ast::LitInt(i, ast::UnsignedIntLit(_)) |
41+
ast::LitInt(i, ast::SignedIntLit(_, ast::Plus)) |
42+
ast::LitInt(i, ast::UnsuffixedIntLit(ast::Plus)) => {
4143
accumulator.push_str(format!("{}", i).as_slice());
4244
}
43-
ast::LitUint(u, _) => {
44-
accumulator.push_str(format!("{}", u).as_slice());
45+
ast::LitInt(i, ast::SignedIntLit(_, ast::Minus)) |
46+
ast::LitInt(i, ast::UnsuffixedIntLit(ast::Minus)) => {
47+
accumulator.push_str(format!("-{}", i).as_slice());
4548
}
4649
ast::LitNil => {}
4750
ast::LitBool(b) => {

src/libsyntax/ext/deriving/generic/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -996,7 +996,7 @@ impl<'a> MethodDef<'a> {
996996
let arms : Vec<ast::Arm> = variants.iter().enumerate()
997997
.map(|(index, &variant)| {
998998
let pat = variant_to_pat(cx, sp, &*variant);
999-
let lit = ast::LitUint(index as u64, ast::TyU);
999+
let lit = ast::LitInt(index as u64, ast::UnsignedIntLit(ast::TyU));
10001000
cx.arm(sp, vec![pat], cx.expr_lit(sp, lit))
10011001
}).collect();
10021002

src/libsyntax/ext/quote.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -189,16 +189,17 @@ pub mod rt {
189189
(signed, $t:ty, $tag:ident) => (
190190
impl ToSource for $t {
191191
fn to_source(&self) -> String {
192-
let lit = dummy_spanned(ast::LitInt(*self as i64, ast::$tag));
193-
pprust::lit_to_string(&lit)
192+
let lit = ast::LitInt(*self as u64, ast::SignedIntLit(ast::$tag,
193+
ast::Sign::new(*self)));
194+
pprust::lit_to_string(&dummy_spanned(lit))
194195
}
195196
}
196197
);
197198
(unsigned, $t:ty, $tag:ident) => (
198199
impl ToSource for $t {
199200
fn to_source(&self) -> String {
200-
let lit = dummy_spanned(ast::LitUint(*self as u64, ast::$tag));
201-
pprust::lit_to_string(&lit)
201+
let lit = ast::LitInt(*self as u64, ast::UnsignedIntLit(ast::$tag));
202+
pprust::lit_to_string(&dummy_spanned(lit))
202203
}
203204
}
204205
);

0 commit comments

Comments
 (0)