mirror of https://github.com/rust-lang/rust.git
Rollup merge of #118903 - azhogin:azhogin/skip_second_stmt_debuginfo.rs, r=petrochenkov
Improved support of collapse_debuginfo attribute for macros. Added walk_chain_collapsed function to consider collapse_debuginfo attribute in parent macros in call chain. Fixed collapse_debuginfo attribute processing for cranelift (there was if/else branches error swap). cc https://github.com/rust-lang/rust/issues/100758
This commit is contained in:
commit
ee7d4c1561
|
@ -68,15 +68,7 @@ impl DebugContext {
|
|||
// 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
|
||||
// annotated with `#[collapse_debuginfo]` or when `-Zdebug-macros` is provided).
|
||||
let span = if tcx.should_collapse_debuginfo(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())
|
||||
};
|
||||
|
||||
let span = tcx.collapsed_debuginfo(span, function_span);
|
||||
match tcx.sess.source_map().lookup_line(span.lo()) {
|
||||
Ok(SourceFileAndLine { sf: file, 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
|
||||
/// 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).
|
||||
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.
|
||||
if self.debug_context.is_none() {
|
||||
return span;
|
||||
}
|
||||
|
||||
if self.cx.tcx().should_collapse_debuginfo(span) {
|
||||
// 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.
|
||||
// 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
|
||||
// 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.
|
||||
// Use span of the outermost expansion site, while keeping the original lexical scope.
|
||||
self.cx.tcx().collapsed_debuginfo(span, self.mir.span)
|
||||
}
|
||||
|
||||
fn spill_operand_to_stack(
|
||||
|
|
|
@ -51,7 +51,7 @@ use rustc_session::lint::LintBuffer;
|
|||
pub use rustc_session::lint::RegisteredTools;
|
||||
use rustc_span::hygiene::MacroKind;
|
||||
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};
|
||||
pub use rustc_target::abi::{ReprFlags, ReprOptions};
|
||||
pub use rustc_type_ir::{DebugWithInfcx, InferCtxtLike, WithInfcx};
|
||||
|
@ -2518,21 +2518,21 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
(ident, scope)
|
||||
}
|
||||
|
||||
/// Returns `true` if the debuginfo for `span` should be collapsed to the outermost expansion
|
||||
/// site. Only applies when `Span` is the result of macro expansion.
|
||||
/// Returns corrected span if the debuginfo for `span` should be collapsed to the outermost
|
||||
/// 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
|
||||
/// 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.
|
||||
///
|
||||
/// When `-Zdebug-macros` is provided then debuginfo will never be collapsed.
|
||||
pub fn should_collapse_debuginfo(self, span: Span) -> bool {
|
||||
!self.sess.opts.unstable_opts.debug_macros
|
||||
&& if self.features().collapse_debuginfo {
|
||||
span.in_macro_expansion_with_collapse_debuginfo()
|
||||
} else {
|
||||
span.from_expansion()
|
||||
}
|
||||
pub fn collapsed_debuginfo(self, span: Span, upto: Span) -> Span {
|
||||
if self.sess.opts.unstable_opts.debug_macros || !span.from_expansion() {
|
||||
return span;
|
||||
}
|
||||
let collapse_debuginfo_enabled = self.features().collapse_debuginfo;
|
||||
hygiene::walk_chain_collapsed(span, upto, collapse_debuginfo_enabled)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
|
@ -445,18 +445,46 @@ impl HygieneData {
|
|||
}
|
||||
|
||||
fn walk_chain(&self, mut span: Span, to: SyntaxContext) -> Span {
|
||||
let orig_span = span;
|
||||
debug!("walk_chain({:?}, {:?})", span, to);
|
||||
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());
|
||||
debug!("walk_chain({:?}): outer_expn={:?}", span, outer_expn);
|
||||
let expn_data = self.expn_data(outer_expn);
|
||||
debug!("walk_chain({:?}): expn_data={:?}", span, expn_data);
|
||||
span = expn_data.call_site;
|
||||
}
|
||||
debug!("walk_chain: for span {:?} >>> return span = {:?}", orig_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> {
|
||||
let mut scope = None;
|
||||
while !self.is_descendant_of(expn_id, self.outer_expn(*ctxt)) {
|
||||
|
@ -573,6 +601,10 @@ pub fn walk_chain(span: Span, to: SyntaxContext) -> Span {
|
|||
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) {
|
||||
// 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| {
|
||||
|
|
|
@ -567,13 +567,6 @@ impl Span {
|
|||
!self.ctxt().is_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.
|
||||
pub fn in_derive_expansion(self) -> bool {
|
||||
matches!(self.ctxt().outer_expn_data().kind, ExpnKind::Macro(MacroKind::Derive, _))
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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…
Reference in New Issue