@@ -14,6 +14,14 @@ use llvm;
14
14
use llvm:: { ConstFCmp , ConstICmp , SetLinkage , SetUnnamedAddr } ;
15
15
use llvm:: { InternalLinkage , ValueRef , Bool , True } ;
16
16
use middle:: { check_const, const_eval, def} ;
17
+ use middle:: const_eval:: { const_int_checked_neg, const_uint_checked_neg} ;
18
+ use middle:: const_eval:: { const_int_checked_add, const_uint_checked_add} ;
19
+ use middle:: const_eval:: { const_int_checked_sub, const_uint_checked_sub} ;
20
+ use middle:: const_eval:: { const_int_checked_mul, const_uint_checked_mul} ;
21
+ use middle:: const_eval:: { const_int_checked_div, const_uint_checked_div} ;
22
+ use middle:: const_eval:: { const_int_checked_rem, const_uint_checked_rem} ;
23
+ use middle:: const_eval:: { const_int_checked_shl, const_uint_checked_shl} ;
24
+ use middle:: const_eval:: { const_int_checked_shr, const_uint_checked_shr} ;
17
25
use trans:: { adt, closure, debuginfo, expr, inline, machine} ;
18
26
use trans:: base:: { self , push_ctxt} ;
19
27
use trans:: common:: * ;
@@ -336,6 +344,7 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
336
344
let csize = machine:: llsize_of_alloc ( cx, val_ty ( llconst) ) ;
337
345
let tsize = machine:: llsize_of_alloc ( cx, llty) ;
338
346
if csize != tsize {
347
+ cx. sess ( ) . abort_if_errors ( ) ;
339
348
unsafe {
340
349
// FIXME these values could use some context
341
350
llvm:: LLVMDumpValue ( llconst) ;
@@ -348,6 +357,100 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
348
357
( llconst, ety_adjusted)
349
358
}
350
359
360
+ fn check_unary_expr_validity ( cx : & CrateContext , e : & ast:: Expr , t : Ty ,
361
+ te : ValueRef ) {
362
+ // The only kind of unary expression that we check for validity
363
+ // here is `-expr`, to check if it "overflows" (e.g. `-i32::MIN`).
364
+ if let ast:: ExprUnary ( ast:: UnNeg , ref inner_e) = e. node {
365
+
366
+ // An unfortunate special case: we parse e.g. -128 as a
367
+ // negation of the literal 128, which means if we're expecting
368
+ // a i8 (or if it was already suffixed, e.g. `-128_i8`), then
369
+ // 128 will have already overflowed to -128, and so then the
370
+ // constant evaluator thinks we're trying to negate -128.
371
+ //
372
+ // Catch this up front by looking for ExprLit directly,
373
+ // and just accepting it.
374
+ if let ast:: ExprLit ( _) = inner_e. node { return ; }
375
+
376
+ let result = match t. sty {
377
+ ty:: ty_int( int_type) => {
378
+ let input = match const_to_opt_int ( te) {
379
+ Some ( v) => v,
380
+ None => return ,
381
+ } ;
382
+ const_int_checked_neg (
383
+ input, e, Some ( const_eval:: IntTy :: from ( cx. tcx ( ) , int_type) ) )
384
+ }
385
+ ty:: ty_uint( uint_type) => {
386
+ let input = match const_to_opt_uint ( te) {
387
+ Some ( v) => v,
388
+ None => return ,
389
+ } ;
390
+ const_uint_checked_neg (
391
+ input, e, Some ( const_eval:: UintTy :: from ( cx. tcx ( ) , uint_type) ) )
392
+ }
393
+ _ => return ,
394
+ } ;
395
+
396
+ // We do not actually care about a successful result.
397
+ if let Err ( err) = result {
398
+ cx. tcx ( ) . sess . span_err ( e. span , & err. description ( ) ) ;
399
+ }
400
+ }
401
+ }
402
+
403
+ fn check_binary_expr_validity ( cx : & CrateContext , e : & ast:: Expr , t : Ty ,
404
+ te1 : ValueRef , te2 : ValueRef ) {
405
+ let b = if let ast:: ExprBinary ( b, _, _) = e. node { b } else { return } ;
406
+
407
+ let result = match t. sty {
408
+ ty:: ty_int( int_type) => {
409
+ let ( lhs, rhs) = match ( const_to_opt_int ( te1) ,
410
+ const_to_opt_int ( te2) ) {
411
+ ( Some ( v1) , Some ( v2) ) => ( v1, v2) ,
412
+ _ => return ,
413
+ } ;
414
+
415
+ let opt_ety = Some ( const_eval:: IntTy :: from ( cx. tcx ( ) , int_type) ) ;
416
+ match b. node {
417
+ ast:: BiAdd => const_int_checked_add ( lhs, rhs, e, opt_ety) ,
418
+ ast:: BiSub => const_int_checked_sub ( lhs, rhs, e, opt_ety) ,
419
+ ast:: BiMul => const_int_checked_mul ( lhs, rhs, e, opt_ety) ,
420
+ ast:: BiDiv => const_int_checked_div ( lhs, rhs, e, opt_ety) ,
421
+ ast:: BiRem => const_int_checked_rem ( lhs, rhs, e, opt_ety) ,
422
+ ast:: BiShl => const_int_checked_shl ( lhs, rhs, e, opt_ety) ,
423
+ ast:: BiShr => const_int_checked_shr ( lhs, rhs, e, opt_ety) ,
424
+ _ => return ,
425
+ }
426
+ }
427
+ ty:: ty_uint( uint_type) => {
428
+ let ( lhs, rhs) = match ( const_to_opt_uint ( te1) ,
429
+ const_to_opt_uint ( te2) ) {
430
+ ( Some ( v1) , Some ( v2) ) => ( v1, v2) ,
431
+ _ => return ,
432
+ } ;
433
+
434
+ let opt_ety = Some ( const_eval:: UintTy :: from ( cx. tcx ( ) , uint_type) ) ;
435
+ match b. node {
436
+ ast:: BiAdd => const_uint_checked_add ( lhs, rhs, e, opt_ety) ,
437
+ ast:: BiSub => const_uint_checked_sub ( lhs, rhs, e, opt_ety) ,
438
+ ast:: BiMul => const_uint_checked_mul ( lhs, rhs, e, opt_ety) ,
439
+ ast:: BiDiv => const_uint_checked_div ( lhs, rhs, e, opt_ety) ,
440
+ ast:: BiRem => const_uint_checked_rem ( lhs, rhs, e, opt_ety) ,
441
+ ast:: BiShl => const_uint_checked_shl ( lhs, rhs, e, opt_ety) ,
442
+ ast:: BiShr => const_uint_checked_shr ( lhs, rhs, e, opt_ety) ,
443
+ _ => return ,
444
+ }
445
+ }
446
+ _ => return ,
447
+ } ;
448
+ // We do not actually care about a successful result.
449
+ if let Err ( err) = result {
450
+ cx. tcx ( ) . sess . span_err ( e. span , & err. description ( ) ) ;
451
+ }
452
+ }
453
+
351
454
fn const_expr_unadjusted < ' a , ' tcx > ( cx : & CrateContext < ' a , ' tcx > ,
352
455
e : & ast:: Expr ,
353
456
ety : Ty < ' tcx > ,
@@ -386,7 +489,8 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
386
489
let signed = ty:: type_is_signed ( intype) ;
387
490
388
491
let ( te2, _) = const_expr ( cx, & * * e2, param_substs) ;
389
- let te2 = base:: cast_shift_const_rhs ( b. node , te1, te2) ;
492
+
493
+ check_binary_expr_validity ( cx, e, ty, te1, te2) ;
390
494
391
495
match b. node {
392
496
ast:: BiAdd => {
@@ -416,8 +520,12 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
416
520
ast:: BiBitXor => llvm:: LLVMConstXor ( te1, te2) ,
417
521
ast:: BiBitAnd => llvm:: LLVMConstAnd ( te1, te2) ,
418
522
ast:: BiBitOr => llvm:: LLVMConstOr ( te1, te2) ,
419
- ast:: BiShl => llvm:: LLVMConstShl ( te1, te2) ,
523
+ ast:: BiShl => {
524
+ let te2 = base:: cast_shift_const_rhs ( b. node , te1, te2) ;
525
+ llvm:: LLVMConstShl ( te1, te2)
526
+ }
420
527
ast:: BiShr => {
528
+ let te2 = base:: cast_shift_const_rhs ( b. node , te1, te2) ;
421
529
if signed { llvm:: LLVMConstAShr ( te1, te2) }
422
530
else { llvm:: LLVMConstLShr ( te1, te2) }
423
531
}
@@ -439,8 +547,11 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
439
547
}
440
548
}
441
549
} ,
442
- ast:: ExprUnary ( u, ref e) => {
443
- let ( te, ty) = const_expr ( cx, & * * e, param_substs) ;
550
+ ast:: ExprUnary ( u, ref inner_e) => {
551
+ let ( te, ty) = const_expr ( cx, & * * inner_e, param_substs) ;
552
+
553
+ check_unary_expr_validity ( cx, e, ty, te) ;
554
+
444
555
let is_float = ty:: type_is_fp ( ty) ;
445
556
match u {
446
557
ast:: UnUniq | ast:: UnDeref => {
@@ -664,7 +775,15 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
664
775
let n = match const_eval:: eval_const_expr_partial ( cx. tcx ( ) , & * * count, None ) {
665
776
Ok ( const_eval:: const_int( i) ) => i as usize ,
666
777
Ok ( const_eval:: const_uint( i) ) => i as usize ,
667
- _ => cx. sess ( ) . span_bug ( count. span , "count must be integral const expression." )
778
+ Ok ( _) => {
779
+ cx. sess ( ) . span_bug ( count. span , "count must be integral const expression." )
780
+ }
781
+ Err ( err) => {
782
+ cx. sess ( ) . span_err ( count. span , & format ! ( "error evaluating count: {}" ,
783
+ err. description( ) ) ) ;
784
+ // return 1 to allow compilation to proceed
785
+ 1 as usize
786
+ }
668
787
} ;
669
788
let unit_val = const_expr ( cx, & * * elem, param_substs) . 0 ;
670
789
let vs: Vec < _ > = repeat ( unit_val) . take ( n) . collect ( ) ;
0 commit comments