@@ -72,6 +72,7 @@ pub enum lint {
72
72
non_uppercase_statics,
73
73
non_uppercase_pattern_statics,
74
74
type_limits,
75
+ type_overflow,
75
76
unused_unsafe,
76
77
77
78
managed_heap_memory,
@@ -219,6 +220,14 @@ static lint_table: &'static [(&'static str, LintSpec)] = &[
219
220
default : warn
220
221
} ) ,
221
222
223
+ ( "type_overflow" ,
224
+ LintSpec {
225
+ lint : type_overflow,
226
+ desc : "literal out of range for its type" ,
227
+ default : warn
228
+ } ) ,
229
+
230
+
222
231
( "unused_unsafe" ,
223
232
LintSpec {
224
233
lint : unused_unsafe,
@@ -321,6 +330,9 @@ struct Context {
321
330
// levels, this stack keeps track of the previous lint levels of whatever
322
331
// was modified.
323
332
lint_stack : ~[ ( lint , level , LintSource ) ] ,
333
+
334
+ // id of the last visited negated expression
335
+ negated_expr_id : ast:: NodeId
324
336
}
325
337
326
338
impl Context {
@@ -507,7 +519,48 @@ fn check_type_limits(cx: &Context, e: &ast::Expr) {
507
519
cx. span_lint ( type_limits, e. span ,
508
520
"comparison is useless due to type limits" ) ;
509
521
}
510
- }
522
+ } ,
523
+ ast:: ExprLit ( lit) => {
524
+ match ty:: get ( ty:: expr_ty ( cx. tcx , e) ) . sty {
525
+ ty:: ty_int( t) => {
526
+ let int_type = if t == ast:: ty_i {
527
+ cx. tcx . sess . targ_cfg . int_type
528
+ } else { t } ;
529
+ let ( min, max) = int_ty_range ( int_type) ;
530
+ let mut lit_val: i64 = match lit. node {
531
+ ast:: lit_int( v, _) => v,
532
+ ast:: lit_uint( v, _) => v as i64 ,
533
+ ast:: lit_int_unsuffixed( v) => v,
534
+ _ => fail ! ( )
535
+ } ;
536
+ if cx. negated_expr_id == e. id {
537
+ lit_val *= -1 ;
538
+ }
539
+ if lit_val < min || lit_val > max {
540
+ cx. span_lint ( type_overflow, e. span ,
541
+ "literal out of range for its type" ) ;
542
+ }
543
+ } ,
544
+ ty:: ty_uint( t) => {
545
+ let uint_type = if t == ast:: ty_u {
546
+ cx. tcx . sess . targ_cfg . uint_type
547
+ } else { t } ;
548
+ let ( min, max) = uint_ty_range ( uint_type) ;
549
+ let lit_val: u64 = match lit. node {
550
+ ast:: lit_int( v, _) => v as u64 ,
551
+ ast:: lit_uint( v, _) => v,
552
+ ast:: lit_int_unsuffixed( v) => v as u64 ,
553
+ _ => fail ! ( )
554
+ } ;
555
+ if lit_val < min || lit_val > max {
556
+ cx. span_lint ( type_overflow, e. span ,
557
+ "literal out of range for its type" ) ;
558
+ }
559
+ } ,
560
+
561
+ _ => ( )
562
+ } ;
563
+ } ,
511
564
_ => ( )
512
565
} ;
513
566
@@ -1078,11 +1131,25 @@ impl Visitor<()> for Context {
1078
1131
}
1079
1132
1080
1133
fn visit_expr ( & mut self , e : @ast:: Expr , _: ( ) ) {
1134
+ match e. node {
1135
+ ast:: ExprUnary ( _, ast:: UnNeg , expr) => {
1136
+ // propagate negation, if the negation itself isn't negated
1137
+ if self . negated_expr_id != e. id {
1138
+ self . negated_expr_id = expr. id ;
1139
+ }
1140
+ } ,
1141
+ ast:: ExprParen ( expr) => if self . negated_expr_id == e. id {
1142
+ self . negated_expr_id = expr. id
1143
+ } ,
1144
+ _ => ( )
1145
+ } ;
1146
+
1081
1147
check_while_true_expr ( self , e) ;
1082
1148
check_stability ( self , e) ;
1083
1149
check_unused_unsafe ( self , e) ;
1084
1150
check_unnecessary_allocation ( self , e) ;
1085
1151
check_heap_expr ( self , e) ;
1152
+
1086
1153
check_type_limits ( self , e) ;
1087
1154
1088
1155
visit:: walk_expr ( self , e, ( ) ) ;
@@ -1139,6 +1206,7 @@ pub fn check_crate(tcx: ty::ctxt, crate: &ast::Crate) {
1139
1206
cur : SmallIntMap :: new ( ) ,
1140
1207
tcx : tcx,
1141
1208
lint_stack : ~[ ] ,
1209
+ negated_expr_id : -1
1142
1210
} ;
1143
1211
1144
1212
// Install default lint levels, followed by the command line levels, and
0 commit comments