caller_location: point to macro invocation sites, like file!/line!.

This commit is contained in:
Eduard-Mihai Burtescu 2019-10-30 18:54:40 +02:00
parent 0b7e28a161
commit c17f89d6ed
5 changed files with 36 additions and 16 deletions

View File

@ -995,7 +995,8 @@ fn get_caller_location(
bx: &mut Bx,
span: Span,
) -> OperandRef<'tcx, Bx::Value> {
let caller = bx.tcx().sess.source_map().lookup_char_pos(span.lo());
let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span);
let caller = bx.tcx().sess.source_map().lookup_char_pos(topmost.lo());
let const_loc = bx.tcx().const_caller_location((
Symbol::intern(&caller.file.name.to_string()),
caller.line as u32,

View File

@ -98,7 +98,8 @@ pub fn emulate_intrinsic(
let intrinsic_name = &self.tcx.item_name(instance.def_id()).as_str()[..];
match intrinsic_name {
"caller_location" => {
let caller = self.tcx.sess.source_map().lookup_char_pos(span.lo());
let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span);
let caller = self.tcx.sess.source_map().lookup_char_pos(topmost.lo());
let location = self.alloc_caller_location(
Symbol::intern(&caller.file.name.to_string()),
caller.line as u32,

View File

@ -954,18 +954,7 @@ pub fn with_mixed_site_ctxt(&self, span: Span) -> Span {
///
/// Stops backtracing at include! boundary.
pub fn expansion_cause(&self) -> Option<Span> {
let mut expn_id = self.current_expansion.id;
let mut last_macro = None;
loop {
let expn_data = expn_id.expn_data();
// Stop going up the backtrace once include! is encountered
if expn_data.is_root() || expn_data.kind.descr() == sym::include {
break;
}
expn_id = expn_data.call_site.ctxt().outer_expn();
last_macro = Some(expn_data.call_site);
}
last_macro
self.current_expansion.id.expansion_cause()
}
pub fn struct_span_warn<S: Into<MultiSpan>>(&self,

View File

@ -28,7 +28,7 @@
use crate::GLOBALS;
use crate::{Span, DUMMY_SP};
use crate::edition::Edition;
use crate::symbol::{kw, Symbol};
use crate::symbol::{kw, sym, Symbol};
use rustc_serialize::{Encodable, Decodable, Encoder, Decoder};
use rustc_data_structures::fx::FxHashMap;
@ -119,6 +119,23 @@ pub fn is_descendant_of(self, ancestor: ExpnId) -> bool {
pub fn outer_expn_is_descendant_of(self, ctxt: SyntaxContext) -> bool {
HygieneData::with(|data| data.is_descendant_of(self, data.outer_expn(ctxt)))
}
/// Returns span for the macro which originally caused this expansion to happen.
///
/// Stops backtracing at include! boundary.
pub fn expansion_cause(mut self) -> Option<Span> {
let mut last_macro = None;
loop {
let expn_data = self.expn_data();
// Stop going up the backtrace once include! is encountered
if expn_data.is_root() || expn_data.kind.descr() == sym::include {
break;
}
self = expn_data.call_site.ctxt().outer_expn();
last_macro = Some(expn_data.call_site);
}
last_macro
}
}
#[derive(Debug)]

View File

@ -1,9 +1,21 @@
// run-pass
#![feature(core_intrinsics)]
macro_rules! caller_location_from_macro {
() => (core::intrinsics::caller_location());
}
fn main() {
let loc = core::intrinsics::caller_location();
assert_eq!(loc.file(), file!());
assert_eq!(loc.line(), 5);
assert_eq!(loc.line(), 10);
assert_eq!(loc.column(), 15);
// `caller_location()` in a macro should behave similarly to `file!` and `line!`,
// i.e. point to where the macro was invoked, instead of the macro itself.
let loc2 = caller_location_from_macro!();
assert_eq!(loc2.file(), file!());
assert_eq!(loc2.line(), 17);
assert_eq!(loc2.column(), 16);
}