99// except according to those terms.
1010
1111use llvm:: { self , ValueRef } ;
12+ use rustc_const_eval:: ErrKind ;
1213use rustc:: middle:: lang_items;
1314use rustc:: ty;
1415use rustc:: mir:: repr as mir;
@@ -222,41 +223,47 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
222223 let const_cond = common:: const_to_opt_uint ( cond) . map ( |c| c == 1 ) ;
223224
224225 // Don't translate the panic block if success if known.
225- let lltarget = self . llblock ( target) ;
226226 if const_cond == Some ( expected) {
227- funclet_br ( bcx, lltarget ) ;
227+ funclet_br ( self , bcx, target ) ;
228228 return ;
229229 }
230230
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 ) ;
233240 } 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) ;
247242 }
248243
244+ // After this point, bcx is the block for the call to panic.
245+ bcx = panic_block. build ( ) ;
246+
249247 // Get the location information.
250248 let loc = bcx. sess ( ) . codemap ( ) . lookup_char_pos ( terminator. span . lo ) ;
251249 let filename = token:: intern_and_get_ident ( & loc. file . name ) ;
252250 let filename = C_str_slice ( bcx. ccx ( ) , filename) ;
253251 let line = C_u32 ( bcx. ccx ( ) , loc. line as u32 ) ;
254252
255253 // 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 {
257255 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+ } ) ;
260267
261268 let file_line = C_struct ( bcx. ccx ( ) , & [ filename, line] , false ) ;
262269 let align = llalign_of_min ( bcx. ccx ( ) , common:: val_ty ( file_line) ) ;
@@ -265,7 +272,8 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
265272 align,
266273 "panic_bounds_check_loc" ) ;
267274 ( lang_items:: PanicBoundsCheckFnLangItem ,
268- vec ! [ file_line, index. immediate( ) , len. immediate( ) ] )
275+ vec ! [ file_line, index, len] ,
276+ const_err)
269277 }
270278 mir:: AssertMessage :: Math ( ref err) => {
271279 let msg_str = token:: intern_and_get_ident ( err. description ( ) ) ;
@@ -278,10 +286,23 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
278286 msg_file_line,
279287 align,
280288 "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 ( ) ) ) )
282292 }
283293 } ;
284294
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+
285306 // Obtain the panic entry point.
286307 let def_id = common:: langcall ( bcx. tcx ( ) , Some ( terminator. span ) , "" , lang_item) ;
287308 let callee = Callee :: def ( bcx. ccx ( ) , def_id,
@@ -290,15 +311,13 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
290311
291312 // Translate the actual panic invoke/call.
292313 if let Some ( unwind) = cleanup {
293- let uwbcx = self . bcx ( unwind) ;
294- let unwind = self . make_landing_pad ( uwbcx) ;
295314 bcx. invoke ( llfn,
296315 & args,
297316 self . unreachable_block ( ) . llbb ,
298- unwind . llbb ( ) ,
299- cleanup_bundle. as_ref ( ) ) ;
317+ llblock ( self , unwind ) ,
318+ cleanup_bundle) ;
300319 } else {
301- bcx. call ( llfn, & args, cleanup_bundle. as_ref ( ) ) ;
320+ bcx. call ( llfn, & args, cleanup_bundle) ;
302321 bcx. unreachable ( ) ;
303322 }
304323 }
0 commit comments