Improved support of collapse_debuginfo attribute for macros.
This commit is contained in:
parent
ca9ff83f1b
commit
f2dbebafad
8 changed files with 513 additions and 39 deletions
|
@ -68,15 +68,7 @@ impl DebugContext {
|
||||||
// In order to have a good line stepping behavior in debugger, we overwrite debug
|
// In order to have a good line stepping behavior in debugger, we overwrite debug
|
||||||
// locations of macro expansions with that of the outermost expansion site (when the macro is
|
// locations of macro expansions with that of the outermost expansion site (when the macro is
|
||||||
// annotated with `#[collapse_debuginfo]` or when `-Zdebug-macros` is provided).
|
// annotated with `#[collapse_debuginfo]` or when `-Zdebug-macros` is provided).
|
||||||
let span = if tcx.should_collapse_debuginfo(span) {
|
let span = tcx.collapsed_debuginfo(span, function_span);
|
||||||
span
|
|
||||||
} else {
|
|
||||||
// Walk up the macro expansion chain until we reach a non-expanded span.
|
|
||||||
// We also stop at the function body level because no line stepping can occur
|
|
||||||
// at the level above that.
|
|
||||||
rustc_span::hygiene::walk_chain(span, function_span.ctxt())
|
|
||||||
};
|
|
||||||
|
|
||||||
match tcx.sess.source_map().lookup_line(span.lo()) {
|
match tcx.sess.source_map().lookup_line(span.lo()) {
|
||||||
Ok(SourceFileAndLine { sf: file, line }) => {
|
Ok(SourceFileAndLine { sf: file, line }) => {
|
||||||
let line_pos = file.lines()[line];
|
let line_pos = file.lines()[line];
|
||||||
|
|
|
@ -228,21 +228,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
/// In order to have a good line stepping behavior in debugger, we overwrite debug
|
/// In order to have a good line stepping behavior in debugger, we overwrite debug
|
||||||
/// locations of macro expansions with that of the outermost expansion site (when the macro is
|
/// locations of macro expansions with that of the outermost expansion site (when the macro is
|
||||||
/// annotated with `#[collapse_debuginfo]` or when `-Zdebug-macros` is provided).
|
/// annotated with `#[collapse_debuginfo]` or when `-Zdebug-macros` is provided).
|
||||||
fn adjust_span_for_debugging(&self, mut span: Span) -> Span {
|
fn adjust_span_for_debugging(&self, span: Span) -> Span {
|
||||||
// Bail out if debug info emission is not enabled.
|
// Bail out if debug info emission is not enabled.
|
||||||
if self.debug_context.is_none() {
|
if self.debug_context.is_none() {
|
||||||
return span;
|
return span;
|
||||||
}
|
}
|
||||||
|
// Walk up the macro expansion chain until we reach a non-expanded span.
|
||||||
if self.cx.tcx().should_collapse_debuginfo(span) {
|
// We also stop at the function body level because no line stepping can occur
|
||||||
// Walk up the macro expansion chain until we reach a non-expanded span.
|
// at the level above that.
|
||||||
// We also stop at the function body level because no line stepping can occur
|
// Use span of the outermost expansion site, while keeping the original lexical scope.
|
||||||
// at the level above that.
|
self.cx.tcx().collapsed_debuginfo(span, self.mir.span)
|
||||||
// Use span of the outermost expansion site, while keeping the original lexical scope.
|
|
||||||
span = rustc_span::hygiene::walk_chain(span, self.mir.span.ctxt());
|
|
||||||
}
|
|
||||||
|
|
||||||
span
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn spill_operand_to_stack(
|
fn spill_operand_to_stack(
|
||||||
|
|
|
@ -50,7 +50,7 @@ use rustc_session::lint::LintBuffer;
|
||||||
pub use rustc_session::lint::RegisteredTools;
|
pub use rustc_session::lint::RegisteredTools;
|
||||||
use rustc_span::hygiene::MacroKind;
|
use rustc_span::hygiene::MacroKind;
|
||||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||||
use rustc_span::{ExpnId, ExpnKind, Span};
|
use rustc_span::{hygiene, ExpnId, ExpnKind, Span};
|
||||||
use rustc_target::abi::{Align, FieldIdx, Integer, IntegerType, VariantIdx};
|
use rustc_target::abi::{Align, FieldIdx, Integer, IntegerType, VariantIdx};
|
||||||
pub use rustc_target::abi::{ReprFlags, ReprOptions};
|
pub use rustc_target::abi::{ReprFlags, ReprOptions};
|
||||||
pub use rustc_type_ir::{DebugWithInfcx, InferCtxtLike, WithInfcx};
|
pub use rustc_type_ir::{DebugWithInfcx, InferCtxtLike, WithInfcx};
|
||||||
|
@ -2515,21 +2515,21 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
(ident, scope)
|
(ident, scope)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if the debuginfo for `span` should be collapsed to the outermost expansion
|
/// Returns corrected span if the debuginfo for `span` should be collapsed to the outermost
|
||||||
/// site. Only applies when `Span` is the result of macro expansion.
|
/// expansion site (with collapse_debuginfo attribute if the corresponding feature enabled).
|
||||||
|
/// Only applies when `Span` is the result of macro expansion.
|
||||||
///
|
///
|
||||||
/// - If the `collapse_debuginfo` feature is enabled then debuginfo is not collapsed by default
|
/// - If the `collapse_debuginfo` feature is enabled then debuginfo is not collapsed by default
|
||||||
/// and only when a macro definition is annotated with `#[collapse_debuginfo]`.
|
/// and only when a (some enclosing) macro definition is annotated with `#[collapse_debuginfo]`.
|
||||||
/// - If `collapse_debuginfo` is not enabled, then debuginfo is collapsed by default.
|
/// - If `collapse_debuginfo` is not enabled, then debuginfo is collapsed by default.
|
||||||
///
|
///
|
||||||
/// When `-Zdebug-macros` is provided then debuginfo will never be collapsed.
|
/// When `-Zdebug-macros` is provided then debuginfo will never be collapsed.
|
||||||
pub fn should_collapse_debuginfo(self, span: Span) -> bool {
|
pub fn collapsed_debuginfo(self, span: Span, upto: Span) -> Span {
|
||||||
!self.sess.opts.unstable_opts.debug_macros
|
if self.sess.opts.unstable_opts.debug_macros || !span.from_expansion() {
|
||||||
&& if self.features().collapse_debuginfo {
|
return span;
|
||||||
span.in_macro_expansion_with_collapse_debuginfo()
|
}
|
||||||
} else {
|
let collapse_debuginfo_enabled = self.features().collapse_debuginfo;
|
||||||
span.from_expansion()
|
hygiene::walk_chain_collapsed(span, upto, collapse_debuginfo_enabled)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -443,18 +443,46 @@ impl HygieneData {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn walk_chain(&self, mut span: Span, to: SyntaxContext) -> Span {
|
fn walk_chain(&self, mut span: Span, to: SyntaxContext) -> Span {
|
||||||
|
let orig_span = span;
|
||||||
debug!("walk_chain({:?}, {:?})", span, to);
|
debug!("walk_chain({:?}, {:?})", span, to);
|
||||||
debug!("walk_chain: span ctxt = {:?}", span.ctxt());
|
debug!("walk_chain: span ctxt = {:?}", span.ctxt());
|
||||||
while span.from_expansion() && span.ctxt() != to {
|
while span.ctxt() != to && span.from_expansion() {
|
||||||
let outer_expn = self.outer_expn(span.ctxt());
|
let outer_expn = self.outer_expn(span.ctxt());
|
||||||
debug!("walk_chain({:?}): outer_expn={:?}", span, outer_expn);
|
debug!("walk_chain({:?}): outer_expn={:?}", span, outer_expn);
|
||||||
let expn_data = self.expn_data(outer_expn);
|
let expn_data = self.expn_data(outer_expn);
|
||||||
debug!("walk_chain({:?}): expn_data={:?}", span, expn_data);
|
debug!("walk_chain({:?}): expn_data={:?}", span, expn_data);
|
||||||
span = expn_data.call_site;
|
span = expn_data.call_site;
|
||||||
}
|
}
|
||||||
|
debug!("walk_chain: for span {:?} >>> return span = {:?}", orig_span, span);
|
||||||
span
|
span
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We need to walk up and update return span if we meet macro instantiation to be collapsed
|
||||||
|
fn walk_chain_collapsed(
|
||||||
|
&self,
|
||||||
|
mut span: Span,
|
||||||
|
to: Span,
|
||||||
|
collapse_debuginfo_enabled: bool,
|
||||||
|
) -> Span {
|
||||||
|
let orig_span = span;
|
||||||
|
let mut ret_span = span;
|
||||||
|
|
||||||
|
debug!("walk_chain_collapsed({:?}, {:?})", span, to);
|
||||||
|
debug!("walk_chain_collapsed: span ctxt = {:?}", span.ctxt());
|
||||||
|
while !span.eq_ctxt(to) && span.from_expansion() {
|
||||||
|
let outer_expn = self.outer_expn(span.ctxt());
|
||||||
|
debug!("walk_chain_collapsed({:?}): outer_expn={:?}", span, outer_expn);
|
||||||
|
let expn_data = self.expn_data(outer_expn);
|
||||||
|
debug!("walk_chain_collapsed({:?}): expn_data={:?}", span, expn_data);
|
||||||
|
span = expn_data.call_site;
|
||||||
|
if !collapse_debuginfo_enabled || expn_data.collapse_debuginfo {
|
||||||
|
ret_span = span;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
debug!("walk_chain_collapsed: for span {:?} >>> return span = {:?}", orig_span, ret_span);
|
||||||
|
ret_span
|
||||||
|
}
|
||||||
|
|
||||||
fn adjust(&self, ctxt: &mut SyntaxContext, expn_id: ExpnId) -> Option<ExpnId> {
|
fn adjust(&self, ctxt: &mut SyntaxContext, expn_id: ExpnId) -> Option<ExpnId> {
|
||||||
let mut scope = None;
|
let mut scope = None;
|
||||||
while !self.is_descendant_of(expn_id, self.outer_expn(*ctxt)) {
|
while !self.is_descendant_of(expn_id, self.outer_expn(*ctxt)) {
|
||||||
|
@ -571,6 +599,10 @@ pub fn walk_chain(span: Span, to: SyntaxContext) -> Span {
|
||||||
HygieneData::with(|data| data.walk_chain(span, to))
|
HygieneData::with(|data| data.walk_chain(span, to))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn walk_chain_collapsed(span: Span, to: Span, collapse_debuginfo_enabled: bool) -> Span {
|
||||||
|
HygieneData::with(|hdata| hdata.walk_chain_collapsed(span, to, collapse_debuginfo_enabled))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn update_dollar_crate_names(mut get_name: impl FnMut(SyntaxContext) -> Symbol) {
|
pub fn update_dollar_crate_names(mut get_name: impl FnMut(SyntaxContext) -> Symbol) {
|
||||||
// The new contexts that need updating are at the end of the list and have `$crate` as a name.
|
// The new contexts that need updating are at the end of the list and have `$crate` as a name.
|
||||||
let (len, to_update) = HygieneData::with(|data| {
|
let (len, to_update) = HygieneData::with(|data| {
|
||||||
|
|
|
@ -568,13 +568,6 @@ impl Span {
|
||||||
self.ctxt() != SyntaxContext::root()
|
self.ctxt() != SyntaxContext::root()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if `span` originates in a macro's expansion where debuginfo should be
|
|
||||||
/// collapsed.
|
|
||||||
pub fn in_macro_expansion_with_collapse_debuginfo(self) -> bool {
|
|
||||||
let outer_expn = self.ctxt().outer_expn_data();
|
|
||||||
matches!(outer_expn.kind, ExpnKind::Macro(..)) && outer_expn.collapse_debuginfo
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns `true` if `span` originates in a derive-macro's expansion.
|
/// Returns `true` if `span` originates in a derive-macro's expansion.
|
||||||
pub fn in_derive_expansion(self) -> bool {
|
pub fn in_derive_expansion(self) -> bool {
|
||||||
matches!(self.ctxt().outer_expn_data().kind, ExpnKind::Macro(MacroKind::Derive, _))
|
matches!(self.ctxt().outer_expn_data().kind, ExpnKind::Macro(MacroKind::Derive, _))
|
||||||
|
|
124
tests/debuginfo/collapse-debuginfo-in-non-collapse-macro.rs
Normal file
124
tests/debuginfo/collapse-debuginfo-in-non-collapse-macro.rs
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
// ignore-lldb
|
||||||
|
#![feature(collapse_debuginfo)]
|
||||||
|
|
||||||
|
// Test that statement, skipped/added/reordered by macros, is correctly processed in debuginfo.
|
||||||
|
// When nested macros instantiations are tagged with collapse_debuginfo attribute,
|
||||||
|
// debug info should be corrected to the first outer macro instantiation
|
||||||
|
// without collapse_debuginfo attribute.
|
||||||
|
// collapse_debuginfo feature enabled.
|
||||||
|
|
||||||
|
// compile-flags:-g
|
||||||
|
|
||||||
|
// === GDB TESTS ===================================================================================
|
||||||
|
|
||||||
|
// gdb-command:run
|
||||||
|
// gdb-command:next
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_rem_call1[...]
|
||||||
|
// gdb-command:step
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_call1_pre[...]
|
||||||
|
// gdb-command:next
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_in_proxy[...]
|
||||||
|
// gdb-command:next 2
|
||||||
|
// gdb-check:[...]#loc_rem_call3[...]
|
||||||
|
// gdb-command:next
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_add_call1[...]
|
||||||
|
// gdb-command:step
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_call1_pre[...]
|
||||||
|
// gdb-command:next
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_in_proxy[...]
|
||||||
|
// gdb-command:next 2
|
||||||
|
// gdb-check:[...]#loc_add_macro[...]
|
||||||
|
// gdb-command:next
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_add_call3[...]
|
||||||
|
// gdb-command:next
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_reorder_call2[...]
|
||||||
|
// gdb-command:next
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_reorder_call3[...]
|
||||||
|
// gdb-command:next
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_reorder_call1[...]
|
||||||
|
// gdb-command:step
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_call1_pre[...]
|
||||||
|
// gdb-command:next
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_in_proxy[...]
|
||||||
|
// gdb-command:next 2
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-command:continue
|
||||||
|
|
||||||
|
#[inline(never)]
|
||||||
|
fn myprintln_impl(text: &str) {
|
||||||
|
println!("{}", text)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[collapse_debuginfo]
|
||||||
|
macro_rules! myprintln {
|
||||||
|
($($arg:tt)*) => {{
|
||||||
|
myprintln_impl($($arg)*);
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! proxy_println {
|
||||||
|
($($arg:tt)*) => {{
|
||||||
|
myprintln!($($arg)*); // #loc_in_proxy
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Macro accepts 3 statements and removes the 2nd statement
|
||||||
|
macro_rules! remove_second_statement {
|
||||||
|
($s1:stmt; $s2:stmt; $s3:stmt;) => { $s1 $s3 }
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! add_second_statement {
|
||||||
|
($s1:stmt; $s3:stmt;) => {
|
||||||
|
$s1
|
||||||
|
call2(); // #loc_add_macro
|
||||||
|
$s3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! reorder_statements {
|
||||||
|
($s1:stmt; $s2:stmt; $s3:stmt;) => { $s2 $s3 $s1 }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call1() {
|
||||||
|
let rv = 0; // #loc_call1_pre
|
||||||
|
proxy_println!("one"); // #loc_call1
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call2() {
|
||||||
|
proxy_println!("two"); // #loc_call2
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call3() {
|
||||||
|
proxy_println!("three"); // #loc_call3
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let ret = 0; // #break, step should go to call1
|
||||||
|
remove_second_statement! { // #loc_rem_hdr
|
||||||
|
call1(); // #loc_rem_call1
|
||||||
|
call2(); // #loc_rem_call2
|
||||||
|
call3(); // #loc_rem_call3
|
||||||
|
}
|
||||||
|
add_second_statement! { // #loc_add_hdr
|
||||||
|
call1(); // #loc_add_call1
|
||||||
|
call3(); // #loc_add_call3
|
||||||
|
}
|
||||||
|
reorder_statements! { // #loc_reorder_hdr
|
||||||
|
call1(); // #loc_reorder_call1
|
||||||
|
call2(); // #loc_reorder_call2
|
||||||
|
call3(); // #loc_reorder_call3
|
||||||
|
}
|
||||||
|
std::process::exit(ret); // #loc_exit
|
||||||
|
}
|
168
tests/debuginfo/skip_second_statement.rs
Normal file
168
tests/debuginfo/skip_second_statement.rs
Normal file
|
@ -0,0 +1,168 @@
|
||||||
|
// ignore-lldb
|
||||||
|
|
||||||
|
// Test that statement, skipped/added/reordered by macros, is correctly processed in debuginfo.
|
||||||
|
// Performed step-over and step-into debug stepping through call statements.
|
||||||
|
// collapse_debuginfo feature disabled.
|
||||||
|
|
||||||
|
// compile-flags:-g
|
||||||
|
|
||||||
|
// === GDB TESTS ===================================================================================
|
||||||
|
|
||||||
|
// gdb-command:run
|
||||||
|
// gdb-command:next
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_rem1_call1[...]
|
||||||
|
// gdb-command:next
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_rem1_call3[...]
|
||||||
|
// gdb-command:next
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_rem2_call1[...]
|
||||||
|
// gdb-command:step
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_call1[...]
|
||||||
|
// gdb-command:next 2
|
||||||
|
// gdb-check:[...]#loc_rem2_call3[...]
|
||||||
|
// gdb-command:step 2
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_call3_println[...]
|
||||||
|
// gdb-command:next 3
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_after_rem[...]
|
||||||
|
// gdb-command:next
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_add1_call1[...]
|
||||||
|
// gdb-command:next
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_add1_hdr[...]
|
||||||
|
// gdb-command:next
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_add1_call3[...]
|
||||||
|
// gdb-command:next
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_add2_call1[...]
|
||||||
|
// gdb-command:step
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_call1[...]
|
||||||
|
// gdb-command:next 2
|
||||||
|
// gdb-check:[...]#loc_add2_hdr[...]
|
||||||
|
// gdb-command:step
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_call2[...]
|
||||||
|
// gdb-command:next 2
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_add2_call3[...]
|
||||||
|
// gdb-command:step 2
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_call3_println[...]
|
||||||
|
// gdb-command:next 3
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_reorder1_call2[...]
|
||||||
|
// gdb-command:next
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_reorder1_call3[...]
|
||||||
|
// gdb-command:next
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_reorder1_call1[...]
|
||||||
|
// gdb-command:next
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_reorder2_call2[...]
|
||||||
|
// gdb-command:step
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_call2[...]
|
||||||
|
// gdb-command:next 2
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_reorder2_call3[...]
|
||||||
|
// gdb-command:step
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_call3[...]
|
||||||
|
// gdb-command:step
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_call3_println[...]
|
||||||
|
// gdb-command:next 3
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_reorder2_call1[...]
|
||||||
|
// gdb-command:step
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_call1[...]
|
||||||
|
// gdb-command:next 2
|
||||||
|
// gdb-command:continue
|
||||||
|
|
||||||
|
#[inline(never)]
|
||||||
|
fn myprintln_impl(text: &str) {
|
||||||
|
println!("{}", text)
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! myprintln {
|
||||||
|
($($arg:tt)*) => {{
|
||||||
|
myprintln_impl($($arg)*);
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Macro accepts 3 statements and removes the 2nd statement
|
||||||
|
macro_rules! remove_second_statement {
|
||||||
|
($s1:stmt; $s2:stmt; $s3:stmt;) => { $s1 $s3 }
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! add_second_statement {
|
||||||
|
($s1:stmt; $s3:stmt;) => {
|
||||||
|
$s1
|
||||||
|
call2(); // #loc_add_macro
|
||||||
|
$s3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! reorder_statements {
|
||||||
|
($s1:stmt; $s2:stmt; $s3:stmt;) => { $s2 $s3 $s1 }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call1() {
|
||||||
|
myprintln!("one"); // #loc_call1
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call2() {
|
||||||
|
myprintln!("two"); // #loc_call2
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call3() {
|
||||||
|
(||{
|
||||||
|
myprintln!("three") // #loc_call3_println
|
||||||
|
})(); // #loc_call3
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let ret = 0; // #break, step should go to call1
|
||||||
|
remove_second_statement! { // #loc_rem1_hdr
|
||||||
|
call1(); // #loc_rem1_call1, breakpoint should set to call1, step should go call3
|
||||||
|
call2(); // #loc_rem1_call2, breakpoint should set to call3
|
||||||
|
call3(); // #loc_rem1_call3
|
||||||
|
}
|
||||||
|
remove_second_statement! { // #loc_rem2_hdr
|
||||||
|
call1(); // #loc_rem2_call1, breakpoint should set to call1, step should go call3
|
||||||
|
call2(); // #loc_rem2_call2, breakpoint should set to call3
|
||||||
|
call3(); // #loc_rem2_call3, breakpoint should set to call3
|
||||||
|
}
|
||||||
|
myprintln!("After remove_second_statement test"); // #loc_after_rem
|
||||||
|
|
||||||
|
add_second_statement! { // #loc_add1_hdr
|
||||||
|
call1(); // #loc_add1_call1
|
||||||
|
call3(); // #loc_add1_call3
|
||||||
|
}
|
||||||
|
add_second_statement! { // #loc_add2_hdr
|
||||||
|
call1(); // #loc_add2_call1
|
||||||
|
call3(); // #loc_add2_call3
|
||||||
|
}
|
||||||
|
|
||||||
|
reorder_statements! { // #loc_reorder1_hdr
|
||||||
|
call1(); // #loc_reorder1_call1
|
||||||
|
call2(); // #loc_reorder1_call2
|
||||||
|
call3(); // #loc_reorder1_call3
|
||||||
|
}
|
||||||
|
reorder_statements! { // #loc_reorder2_hdr
|
||||||
|
call1(); // #loc_reorder2_call1
|
||||||
|
call2(); // #loc_reorder2_call2
|
||||||
|
call3(); // #loc_reorder2_call3
|
||||||
|
}
|
||||||
|
|
||||||
|
std::process::exit(ret); // #loc_exit
|
||||||
|
}
|
170
tests/debuginfo/skip_second_statement_collapse.rs
Normal file
170
tests/debuginfo/skip_second_statement_collapse.rs
Normal file
|
@ -0,0 +1,170 @@
|
||||||
|
// ignore-lldb
|
||||||
|
#![feature(collapse_debuginfo)]
|
||||||
|
|
||||||
|
// Test that statement, skipped/added/reordered by macros, is correctly processed in debuginfo
|
||||||
|
// Performed step-over and step-into debug stepping through call statements.
|
||||||
|
// collapse_debuginfo feature enabled.
|
||||||
|
|
||||||
|
// compile-flags:-g
|
||||||
|
|
||||||
|
// === GDB TESTS ===================================================================================
|
||||||
|
|
||||||
|
// gdb-command:run
|
||||||
|
// gdb-command:next
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_rem1_call1[...]
|
||||||
|
// gdb-command:next
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_rem1_call3[...]
|
||||||
|
// gdb-command:next
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_rem2_call1[...]
|
||||||
|
// gdb-command:step
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_call1[...]
|
||||||
|
// gdb-command:next 2
|
||||||
|
// gdb-check:[...]#loc_rem2_call3[...]
|
||||||
|
// gdb-command:step 2
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_call3_println[...]
|
||||||
|
// gdb-command:next 3
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_after_rem[...]
|
||||||
|
// gdb-command:next
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_add1_call1[...]
|
||||||
|
// gdb-command:next
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_add_macro[...]
|
||||||
|
// gdb-command:next
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_add1_call3[...]
|
||||||
|
// gdb-command:next
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_add2_call1[...]
|
||||||
|
// gdb-command:step
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_call1[...]
|
||||||
|
// gdb-command:next 2
|
||||||
|
// gdb-check:[...]#loc_add_macro[...]
|
||||||
|
// gdb-command:step
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_call2[...]
|
||||||
|
// gdb-command:next 2
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_add2_call3[...]
|
||||||
|
// gdb-command:step 2
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_call3_println[...]
|
||||||
|
// gdb-command:next 3
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_reorder1_call2[...]
|
||||||
|
// gdb-command:next
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_reorder1_call3[...]
|
||||||
|
// gdb-command:next
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_reorder1_call1[...]
|
||||||
|
// gdb-command:next
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_reorder2_call2[...]
|
||||||
|
// gdb-command:step
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_call2[...]
|
||||||
|
// gdb-command:next 2
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_reorder2_call3[...]
|
||||||
|
// gdb-command:step
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_call3[...]
|
||||||
|
// gdb-command:step
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_call3_println[...]
|
||||||
|
// gdb-command:next 3
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_reorder2_call1[...]
|
||||||
|
// gdb-command:step
|
||||||
|
// gdb-command:frame
|
||||||
|
// gdb-check:[...]#loc_call1[...]
|
||||||
|
// gdb-command:next 2
|
||||||
|
// gdb-command:continue
|
||||||
|
|
||||||
|
#[inline(never)]
|
||||||
|
fn myprintln_impl(text: &str) {
|
||||||
|
println!("{}", text)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[collapse_debuginfo]
|
||||||
|
macro_rules! myprintln {
|
||||||
|
($($arg:tt)*) => {{
|
||||||
|
myprintln_impl($($arg)*);
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Macro accepts 3 statements and removes the 2nd statement
|
||||||
|
macro_rules! remove_second_statement {
|
||||||
|
($s1:stmt; $s2:stmt; $s3:stmt;) => { $s1 $s3 }
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! add_second_statement {
|
||||||
|
($s1:stmt; $s3:stmt;) => {
|
||||||
|
$s1
|
||||||
|
call2(); // #loc_add_macro
|
||||||
|
$s3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! reorder_statements {
|
||||||
|
($s1:stmt; $s2:stmt; $s3:stmt;) => { $s2 $s3 $s1 }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call1() {
|
||||||
|
myprintln!("one"); // #loc_call1
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call2() {
|
||||||
|
myprintln!("two"); // #loc_call2
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call3() {
|
||||||
|
(||{
|
||||||
|
myprintln!("three") // #loc_call3_println
|
||||||
|
})(); // #loc_call3
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let ret = 0; // #break, step should go to call1
|
||||||
|
remove_second_statement! { // #loc_rem1_hdr
|
||||||
|
call1(); // #loc_rem1_call1, breakpoint should set to call1, step should go call3
|
||||||
|
call2(); // #loc_rem1_call2, breakpoint should set to call3
|
||||||
|
call3(); // #loc_rem1_call3
|
||||||
|
}
|
||||||
|
remove_second_statement! { // #loc_rem2_hdr
|
||||||
|
call1(); // #loc_rem2_call1, breakpoint should set to call1, step should go call3
|
||||||
|
call2(); // #loc_rem2_call2, breakpoint should set to call3
|
||||||
|
call3(); // #loc_rem2_call3, breakpoint should set to call3
|
||||||
|
}
|
||||||
|
myprintln!("After remove_second_statement test"); // #loc_after_rem
|
||||||
|
|
||||||
|
add_second_statement! { // #loc_add1_hdr
|
||||||
|
call1(); // #loc_add1_call1
|
||||||
|
call3(); // #loc_add1_call3
|
||||||
|
}
|
||||||
|
add_second_statement! { // #loc_add2_hdr
|
||||||
|
call1(); // #loc_add2_call1
|
||||||
|
call3(); // #loc_add2_call3
|
||||||
|
}
|
||||||
|
|
||||||
|
reorder_statements! { // #loc_reorder1_hdr
|
||||||
|
call1(); // #loc_reorder1_call1
|
||||||
|
call2(); // #loc_reorder1_call2
|
||||||
|
call3(); // #loc_reorder1_call3
|
||||||
|
}
|
||||||
|
reorder_statements! { // #loc_reorder2_hdr
|
||||||
|
call1(); // #loc_reorder2_call1
|
||||||
|
call2(); // #loc_reorder2_call2
|
||||||
|
call3(); // #loc_reorder2_call3
|
||||||
|
}
|
||||||
|
|
||||||
|
std::process::exit(ret); // #loc_exit
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue