@@ -405,7 +405,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
405405 self . set_debug_loc ( & mut bx, terminator. source_info ) ;
406406
407407 // Get the location information.
408- let location = self . get_caller_location ( & mut bx, span ) . immediate ( ) ;
408+ let location = self . get_caller_location ( & mut bx, terminator . source_info ) . immediate ( ) ;
409409
410410 // Put together the arguments to the panic entry point.
411411 let ( lang_item, args) = match msg {
@@ -442,7 +442,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
442442 bx : & mut Bx ,
443443 intrinsic : Option < Symbol > ,
444444 instance : Option < Instance < ' tcx > > ,
445- span : Span ,
445+ source_info : mir :: SourceInfo ,
446446 destination : & Option < ( mir:: Place < ' tcx > , mir:: BasicBlock ) > ,
447447 cleanup : Option < mir:: BasicBlock > ,
448448 ) -> bool {
@@ -484,11 +484,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
484484 }
485485 } ) ;
486486 let msg = bx. const_str ( Symbol :: intern ( & msg_str) ) ;
487- let location = self . get_caller_location ( bx, span ) . immediate ( ) ;
487+ let location = self . get_caller_location ( bx, source_info ) . immediate ( ) ;
488488
489489 // Obtain the panic entry point.
490490 // FIXME: dedup this with `codegen_assert_terminator` above.
491- let def_id = common:: langcall ( bx. tcx ( ) , Some ( span) , "" , LangItem :: Panic ) ;
491+ let def_id =
492+ common:: langcall ( bx. tcx ( ) , Some ( source_info. span ) , "" , LangItem :: Panic ) ;
492493 let instance = ty:: Instance :: mono ( bx. tcx ( ) , def_id) ;
493494 let fn_abi = FnAbi :: of_instance ( bx, instance, & [ ] ) ;
494495 let llfn = bx. get_fn_addr ( instance) ;
@@ -529,7 +530,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
529530 cleanup : Option < mir:: BasicBlock > ,
530531 fn_span : Span ,
531532 ) {
532- let span = terminator. source_info . span ;
533+ let source_info = terminator. source_info ;
534+ let span = source_info. span ;
535+
533536 // Create the callee. This is a fn ptr or zero-sized and hence a kind of scalar.
534537 let callee = self . codegen_operand ( & mut bx, func) ;
535538
@@ -606,7 +609,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
606609 & mut bx,
607610 intrinsic,
608611 instance,
609- span ,
612+ source_info ,
610613 destination,
611614 cleanup,
612615 ) {
@@ -627,7 +630,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
627630
628631 if intrinsic == Some ( sym:: caller_location) {
629632 if let Some ( ( _, target) ) = destination. as_ref ( ) {
630- let location = self . get_caller_location ( & mut bx, fn_span) ;
633+ let location = self
634+ . get_caller_location ( & mut bx, mir:: SourceInfo { span : fn_span, ..source_info } ) ;
631635
632636 if let ReturnDest :: IndirectOperand ( tmp, _) = ret_dest {
633637 location. val . store ( & mut bx, tmp) ;
@@ -686,7 +690,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
686690 & fn_abi,
687691 & args,
688692 dest,
689- terminator . source_info . span ,
693+ span,
690694 ) ;
691695
692696 if let ReturnDest :: IndirectOperand ( dst, _) = ret_dest {
@@ -793,7 +797,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
793797 args. len( ) + 1 ,
794798 "#[track_caller] fn's must have 1 more argument in their ABI than in their MIR" ,
795799 ) ;
796- let location = self . get_caller_location ( & mut bx, fn_span) ;
800+ let location =
801+ self . get_caller_location ( & mut bx, mir:: SourceInfo { span : fn_span, ..source_info } ) ;
797802 debug ! (
798803 "codegen_call_terminator({:?}): location={:?} (fn_span {:?})" ,
799804 terminator, location, fn_span
@@ -1179,17 +1184,49 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
11791184 }
11801185 }
11811186
1182- fn get_caller_location ( & mut self , bx : & mut Bx , span : Span ) -> OperandRef < ' tcx , Bx :: Value > {
1183- self . caller_location . unwrap_or_else ( || {
1187+ fn get_caller_location (
1188+ & mut self ,
1189+ bx : & mut Bx ,
1190+ mut source_info : mir:: SourceInfo ,
1191+ ) -> OperandRef < ' tcx , Bx :: Value > {
1192+ let tcx = bx. tcx ( ) ;
1193+
1194+ let mut span_to_caller_location = |span : Span | {
11841195 let topmost = span. ctxt ( ) . outer_expn ( ) . expansion_cause ( ) . unwrap_or ( span) ;
1185- let caller = bx . tcx ( ) . sess . source_map ( ) . lookup_char_pos ( topmost. lo ( ) ) ;
1186- let const_loc = bx . tcx ( ) . const_caller_location ( (
1196+ let caller = tcx. sess . source_map ( ) . lookup_char_pos ( topmost. lo ( ) ) ;
1197+ let const_loc = tcx. const_caller_location ( (
11871198 Symbol :: intern ( & caller. file . name . to_string ( ) ) ,
11881199 caller. line as u32 ,
11891200 caller. col_display as u32 + 1 ,
11901201 ) ) ;
11911202 OperandRef :: from_const ( bx, const_loc, bx. tcx ( ) . caller_location_ty ( ) )
1192- } )
1203+ } ;
1204+
1205+ // Walk up the `SourceScope`s, in case some of them are from MIR inlining.
1206+ // If so, the starting `source_info.span` is in the innermost inlined
1207+ // function, and will be replaced with outer callsite spans as long
1208+ // as the inlined functions were `#[track_caller]`.
1209+ loop {
1210+ let scope_data = & self . mir . source_scopes [ source_info. scope ] ;
1211+
1212+ if let Some ( ( callee, callsite_span) ) = scope_data. inlined {
1213+ // Stop inside the most nested non-`#[track_caller]` function,
1214+ // before ever reaching its caller (which is irrelevant).
1215+ if !callee. def . requires_caller_location ( tcx) {
1216+ return span_to_caller_location ( source_info. span ) ;
1217+ }
1218+ source_info. span = callsite_span;
1219+ }
1220+
1221+ // Skip past all of the parents with `inlined: None`.
1222+ match scope_data. inlined_parent_scope {
1223+ Some ( parent) => source_info. scope = parent,
1224+ None => break ,
1225+ }
1226+ }
1227+
1228+ // No inlined `SourceScope`s, or all of them were `#[track_caller]`.
1229+ self . caller_location . unwrap_or_else ( || span_to_caller_location ( source_info. span ) )
11931230 }
11941231
11951232 fn get_personality_slot ( & mut self , bx : & mut Bx ) -> PlaceRef < ' tcx , Bx :: Value > {
0 commit comments