9
9
// except according to those terms.
10
10
11
11
use llvm:: { self , ValueRef } ;
12
+ use rustc_const_eval:: ErrKind ;
12
13
use rustc:: middle:: lang_items;
13
14
use rustc:: ty;
14
15
use rustc:: mir:: repr as mir;
@@ -222,41 +223,47 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
222
223
let const_cond = common:: const_to_opt_uint ( cond) . map ( |c| c == 1 ) ;
223
224
224
225
// Don't translate the panic block if success if known.
225
- let lltarget = self . llblock ( target) ;
226
226
if const_cond == Some ( expected) {
227
- funclet_br ( bcx, lltarget ) ;
227
+ funclet_br ( self , bcx, target ) ;
228
228
return ;
229
229
}
230
230
231
- if const_cond == Some ( !expected) {
232
- // Do nothing to end up with an unconditional panic.
231
+ // Pass the condition through llvm.expect for branch hinting.
232
+ let expect = bcx. ccx ( ) . get_intrinsic ( & "llvm.expect.i1" ) ;
233
+ let cond = bcx. call ( expect, & [ cond, C_bool ( bcx. ccx ( ) , expected) ] , None ) ;
234
+
235
+ // Create the failure block and the conditional branch to it.
236
+ let lltarget = llblock ( self , target) ;
237
+ let panic_block = self . fcx . new_block ( "panic" , None ) ;
238
+ if expected {
239
+ bcx. cond_br ( cond, lltarget, panic_block. llbb ) ;
233
240
} else {
234
- // Pass the condition through llvm.expect for branch hinting.
235
- let expect = bcx. ccx ( ) . get_intrinsic ( & "llvm.expect.i1" ) ;
236
- let cond = bcx. call ( expect, & [ cond, C_bool ( bcx. ccx ( ) , expected) ] , None ) ;
237
-
238
- // Create the failure block and the conditional branch to it.
239
- // After this point, bcx is the block for the call to panic.
240
- let panic_block = self . fcx . new_block ( "panic" , None ) ;
241
- if expected {
242
- bcx. cond_br ( cond, lltarget, panic_block. llbb ) ;
243
- } else {
244
- bcx. cond_br ( cond, panic_block. llbb , lltarget) ;
245
- }
246
- bcx = panic_block. build ( ) ;
241
+ bcx. cond_br ( cond, panic_block. llbb , lltarget) ;
247
242
}
248
243
244
+ // After this point, bcx is the block for the call to panic.
245
+ bcx = panic_block. build ( ) ;
246
+
249
247
// Get the location information.
250
248
let loc = bcx. sess ( ) . codemap ( ) . lookup_char_pos ( terminator. span . lo ) ;
251
249
let filename = token:: intern_and_get_ident ( & loc. file . name ) ;
252
250
let filename = C_str_slice ( bcx. ccx ( ) , filename) ;
253
251
let line = C_u32 ( bcx. ccx ( ) , loc. line as u32 ) ;
254
252
255
253
// Put together the arguments to the panic entry point.
256
- let ( lang_item, args) = match * msg {
254
+ let ( lang_item, args, const_err ) = match * msg {
257
255
mir:: AssertMessage :: BoundsCheck { ref len, ref index } => {
258
- let len = self . trans_operand ( & mut bcx, len) ;
259
- let index = self . trans_operand ( & mut bcx, index) ;
256
+ let len = self . trans_operand ( & mut bcx, len) . immediate ( ) ;
257
+ let index = self . trans_operand ( & mut bcx, index) . immediate ( ) ;
258
+
259
+ let const_err = common:: const_to_opt_uint ( len) . and_then ( |len| {
260
+ common:: const_to_opt_uint ( index) . map ( |index| {
261
+ ErrKind :: IndexOutOfBounds {
262
+ len : len,
263
+ index : index
264
+ }
265
+ } )
266
+ } ) ;
260
267
261
268
let file_line = C_struct ( bcx. ccx ( ) , & [ filename, line] , false ) ;
262
269
let align = llalign_of_min ( bcx. ccx ( ) , common:: val_ty ( file_line) ) ;
@@ -265,7 +272,8 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
265
272
align,
266
273
"panic_bounds_check_loc" ) ;
267
274
( lang_items:: PanicBoundsCheckFnLangItem ,
268
- vec ! [ file_line, index. immediate( ) , len. immediate( ) ] )
275
+ vec ! [ file_line, index, len] ,
276
+ const_err)
269
277
}
270
278
mir:: AssertMessage :: Math ( ref err) => {
271
279
let msg_str = token:: intern_and_get_ident ( err. description ( ) ) ;
@@ -278,10 +286,23 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
278
286
msg_file_line,
279
287
align,
280
288
"panic_loc" ) ;
281
- ( lang_items:: PanicFnLangItem , vec ! [ msg_file_line] )
289
+ ( lang_items:: PanicFnLangItem ,
290
+ vec ! [ msg_file_line] ,
291
+ Some ( ErrKind :: Math ( err. clone ( ) ) ) )
282
292
}
283
293
} ;
284
294
295
+ // If we know we always panic, and the error message
296
+ // is also constant, then we can produce a warning.
297
+ if const_cond == Some ( !expected) {
298
+ if let Some ( err) = const_err {
299
+ let _ = consts:: const_err ( bcx. ccx ( ) ,
300
+ terminator. span ,
301
+ Err :: < ( ) , _ > ( err) ,
302
+ consts:: TrueConst :: No ) ;
303
+ }
304
+ }
305
+
285
306
// Obtain the panic entry point.
286
307
let def_id = common:: langcall ( bcx. tcx ( ) , Some ( terminator. span ) , "" , lang_item) ;
287
308
let callee = Callee :: def ( bcx. ccx ( ) , def_id,
@@ -290,15 +311,13 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
290
311
291
312
// Translate the actual panic invoke/call.
292
313
if let Some ( unwind) = cleanup {
293
- let uwbcx = self . bcx ( unwind) ;
294
- let unwind = self . make_landing_pad ( uwbcx) ;
295
314
bcx. invoke ( llfn,
296
315
& args,
297
316
self . unreachable_block ( ) . llbb ,
298
- unwind . llbb ( ) ,
299
- cleanup_bundle. as_ref ( ) ) ;
317
+ llblock ( self , unwind ) ,
318
+ cleanup_bundle) ;
300
319
} else {
301
- bcx. call ( llfn, & args, cleanup_bundle. as_ref ( ) ) ;
320
+ bcx. call ( llfn, & args, cleanup_bundle) ;
302
321
bcx. unreachable ( ) ;
303
322
}
304
323
}
0 commit comments