Skip to content

Commit 9c7d9eb

Browse files
debuginfo: Add support for argument shadowing.
1 parent 33e7d95 commit 9c7d9eb

File tree

3 files changed

+110
-36
lines changed

3 files changed

+110
-36
lines changed

src/librustc/middle/trans/common.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,8 +230,6 @@ pub struct FunctionContext {
230230
ccx: @mut CrateContext,
231231

232232
// Used and maintained by the debuginfo module.
233-
// @jdm: Not sure if the Option-wrapper is a good idea. It allows to save some space in
234-
// non-debug builds, but generates quite a bit of noise at usage sites. What's your opinion?
235233
debug_context: Option<~debuginfo::FunctionDebugContext>
236234
}
237235

src/librustc/middle/trans/debuginfo.rs

Lines changed: 51 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -271,32 +271,32 @@ pub fn create_function_metadata(fcx: &mut FunctionContext) -> DISubprogram {
271271
let cx = fcx.ccx;
272272

273273
let fnitem = cx.tcx.items.get_copy(&fcx.id);
274-
let (ident, ret_ty, id) = match fnitem {
274+
let (ident, fn_decl, id) = match fnitem {
275275
ast_map::node_item(ref item, _) => {
276276
match item.node {
277-
ast::item_fn(ast::fn_decl { output: ref ty, _}, _, _, _, _) => {
278-
(item.ident, ty, item.id)
277+
ast::item_fn(ref fn_decl, _, _, _, _) => {
278+
(item.ident, fn_decl, item.id)
279279
}
280280
_ => fcx.ccx.sess.span_bug(item.span,
281281
"create_function_metadata: item bound to non-function")
282282
}
283283
}
284284
ast_map::node_method(
285285
@ast::method {
286-
decl: ast::fn_decl { output: ref ty, _ },
286+
decl: ref fn_decl,
287287
id: id,
288288
ident: ident,
289289
_
290290
},
291291
_,
292292
_) => {
293-
(ident, ty, id)
293+
(ident, fn_decl, id)
294294
}
295295
ast_map::node_expr(ref expr) => {
296296
match expr.node {
297-
ast::expr_fn_block(ref decl, _) => {
297+
ast::expr_fn_block(ref fn_decl, _) => {
298298
let name = gensym_name("fn");
299-
(name, &decl.output, expr.id)
299+
(name, fn_decl, expr.id)
300300
}
301301
_ => fcx.ccx.sess.span_bug(expr.span,
302302
"create_function_metadata: expected an expr_fn_block here")
@@ -305,14 +305,14 @@ pub fn create_function_metadata(fcx: &mut FunctionContext) -> DISubprogram {
305305
ast_map::node_trait_method(
306306
@ast::provided(
307307
@ast::method {
308-
decl: ast::fn_decl { output: ref ty, _ },
308+
decl: ref fn_decl,
309309
id: id,
310310
ident: ident,
311311
_
312312
}),
313313
_,
314314
_) => {
315-
(ident, ty, id)
315+
(ident, fn_decl, id)
316316
}
317317
_ => fcx.ccx.sess.bug(fmt!("create_function_metadata: unexpected sort of node: %?", fnitem))
318318
};
@@ -335,9 +335,9 @@ pub fn create_function_metadata(fcx: &mut FunctionContext) -> DISubprogram {
335335
let file_metadata = file_metadata(cx, loc.file.name);
336336

337337
let return_type_metadata = if cx.sess.opts.extra_debuginfo {
338-
match ret_ty.node {
338+
match fn_decl.output.node {
339339
ast::ty_nil => ptr::null(),
340-
_ => type_metadata(cx, ty::node_id_to_type(cx.tcx, id), ret_ty.span)
340+
_ => type_metadata(cx, ty::node_id_to_type(cx.tcx, id), fn_decl.output.span)
341341
}
342342
} else {
343343
ptr::null()
@@ -382,7 +382,9 @@ pub fn create_function_metadata(fcx: &mut FunctionContext) -> DISubprogram {
382382
match *entry_block {
383383
ast_map::node_block(ref block) => {
384384
let scope_map = &mut fn_debug_context.scope_map;
385-
populate_scope_map(cx, block, fn_metadata, scope_map);
385+
let arg_pats = do fn_decl.inputs.map |arg_ref| { arg_ref.pat };
386+
387+
populate_scope_map(cx, arg_pats, block, fn_metadata, scope_map);
386388
}
387389
_ => cx.sess.span_bug(span,
388390
fmt!("debuginfo::create_function_metadata() - \
@@ -1278,9 +1280,11 @@ fn DIB(cx: &CrateContext) -> DIBuilderRef {
12781280
// descriptors where necessary. These artificial scopes allow GDB to correctly handle name
12791281
// shadowing.
12801282
fn populate_scope_map(cx: &mut CrateContext,
1283+
arg_pats: &[@ast::pat],
12811284
fn_entry_block: &ast::Block,
12821285
fn_metadata: DISubprogram,
12831286
scope_map: &mut HashMap<ast::NodeId, DIScope>) {
1287+
let def_map = cx.tcx.def_map;
12841288

12851289
struct ScopeStackEntry {
12861290
scope_metadata: DIScope,
@@ -1289,6 +1293,15 @@ fn populate_scope_map(cx: &mut CrateContext,
12891293

12901294
let mut scope_stack = ~[ScopeStackEntry { scope_metadata: fn_metadata, ident: None }];
12911295

1296+
// Push argument identifiers onto the stack so arguments integrate nicely with variable
1297+
// shadowing.
1298+
for &arg_pat in arg_pats.iter() {
1299+
do pat_util::pat_bindings(def_map, arg_pat) |_, _, _, path_ref| {
1300+
let ident = ast_util::path_to_ident(path_ref);
1301+
scope_stack.push(ScopeStackEntry { scope_metadata: fn_metadata, ident: Some(ident) });
1302+
}
1303+
}
1304+
12921305
walk_block(cx, fn_entry_block, &mut scope_stack, scope_map);
12931306

12941307
// local helper functions for walking the AST.
@@ -1300,7 +1313,6 @@ fn populate_scope_map(cx: &mut CrateContext,
13001313
inner_walk: &fn(&mut CrateContext,
13011314
&mut ~[ScopeStackEntry],
13021315
&mut HashMap<ast::NodeId, DIScope>)) {
1303-
13041316
// Create a new lexical scope and push it onto the stack
13051317
let loc = cx.sess.codemap.lookup_char_pos(scope_span.lo);
13061318
let file_metadata = file_metadata(cx, loc.file.name);
@@ -1335,7 +1347,6 @@ fn populate_scope_map(cx: &mut CrateContext,
13351347
block: &ast::Block,
13361348
scope_stack: &mut ~[ScopeStackEntry],
13371349
scope_map: &mut HashMap<ast::NodeId, DIScope>) {
1338-
13391350
scope_map.insert(block.id, scope_stack.last().scope_metadata);
13401351

13411352
// The interesting things here are statements and the concluding expression.
@@ -1361,7 +1372,6 @@ fn populate_scope_map(cx: &mut CrateContext,
13611372
scope_map: &mut HashMap<ast::NodeId, DIScope>) {
13621373
match *decl {
13631374
codemap::spanned { node: ast::decl_local(@ref local), _ } => {
1364-
13651375
scope_map.insert(local.id, scope_stack.last().scope_metadata);
13661376

13671377
walk_pattern(cx, local.pat, scope_stack, scope_map);
@@ -1383,7 +1393,7 @@ fn populate_scope_map(cx: &mut CrateContext,
13831393

13841394
// Unfortunately, we cannot just use pat_util::pat_bindings() or ast_util::walk_pat() here
13851395
// because we have to visit *all* nodes in order to put them into the scope map. The above
1386-
// function don't do that.
1396+
// functions don't do that.
13871397
match pat.node {
13881398
ast::pat_ident(_, ref path_ref, ref sub_pat_opt) => {
13891399

@@ -1412,9 +1422,8 @@ fn populate_scope_map(cx: &mut CrateContext,
14121422

14131423
// Is there already a binding with that name?
14141424
let need_new_scope = scope_stack
1415-
.rev_iter()
1416-
.find_(|entry| entry.ident.iter().any(|i| *i == ident))
1417-
.is_some();
1425+
.iter()
1426+
.any(|entry| entry.ident.iter().any(|i| *i == ident));
14181427

14191428
if need_new_scope {
14201429
// Create a new lexical scope and push it onto the stack
@@ -1574,8 +1583,10 @@ fn populate_scope_map(cx: &mut CrateContext,
15741583
ast::expr_if(@ref cond_exp, ref then_block, ref opt_else_exp) => {
15751584
walk_expr(cx, cond_exp, scope_stack, scope_map);
15761585

1577-
do with_new_scope(cx, then_block.span, scope_stack, scope_map) |c, s, m| {
1578-
walk_block(c, then_block, s, m);
1586+
do with_new_scope(cx, then_block.span, scope_stack, scope_map) |cx,
1587+
scope_stack,
1588+
scope_map| {
1589+
walk_block(cx, then_block, scope_stack, scope_map);
15791590
}
15801591

15811592
match *opt_else_exp {
@@ -1587,8 +1598,10 @@ fn populate_scope_map(cx: &mut CrateContext,
15871598
ast::expr_while(@ref cond_exp, ref loop_body) => {
15881599
walk_expr(cx, cond_exp, scope_stack, scope_map);
15891600

1590-
do with_new_scope(cx, loop_body.span, scope_stack, scope_map) |c, s, m| {
1591-
walk_block(c, loop_body, s, m);
1601+
do with_new_scope(cx, loop_body.span, scope_stack, scope_map) |cx,
1602+
scope_stack,
1603+
scope_map| {
1604+
walk_block(cx, loop_body, scope_stack, scope_map);
15921605
}
15931606
}
15941607

@@ -1604,20 +1617,22 @@ fn populate_scope_map(cx: &mut CrateContext,
16041617

16051618
ast::expr_loop(ref block, _) |
16061619
ast::expr_block(ref block) => {
1607-
do with_new_scope(cx, block.span, scope_stack, scope_map) |c, s, m| {
1608-
walk_block(c, block, s, m);
1620+
do with_new_scope(cx, block.span, scope_stack, scope_map) |cx,
1621+
scope_stack,
1622+
scope_map| {
1623+
walk_block(cx, block, scope_stack, scope_map);
16091624
}
16101625
}
16111626

16121627
ast::expr_fn_block(ast::fn_decl { inputs: ref inputs, _ }, ref block) => {
1613-
1614-
do with_new_scope(cx, block.span, scope_stack, scope_map) |c, s, m| {
1615-
1628+
do with_new_scope(cx, block.span, scope_stack, scope_map) |cx,
1629+
scope_stack,
1630+
scope_map| {
16161631
for &ast::arg { pat: pattern, _ } in inputs.iter() {
1617-
walk_pattern(c, pattern, s, m);
1632+
walk_pattern(cx, pattern, scope_stack, scope_map);
16181633
}
16191634

1620-
walk_block(c, block, s, m);
1635+
walk_block(cx, block, scope_stack, scope_map);
16211636
}
16221637
}
16231638

@@ -1663,14 +1678,16 @@ fn populate_scope_map(cx: &mut CrateContext,
16631678
for arm_ref in arms.iter() {
16641679
let arm_span = arm_ref.pats[0].span;
16651680

1666-
do with_new_scope(cx, arm_span, scope_stack, scope_map) |c, s, m| {
1667-
walk_pattern(c, arm_ref.pats[0], s, m);
1681+
do with_new_scope(cx, arm_span, scope_stack, scope_map) |cx,
1682+
scope_stack,
1683+
scope_map| {
1684+
walk_pattern(cx, arm_ref.pats[0], scope_stack, scope_map);
16681685

16691686
for &@ref guard_exp in arm_ref.guard.iter() {
1670-
walk_expr(c, guard_exp, s, m)
1687+
walk_expr(cx, guard_exp, scope_stack, scope_map)
16711688
}
16721689

1673-
walk_block(c, &arm_ref.body, s, m);
1690+
walk_block(cx, &arm_ref.body, scope_stack, scope_map);
16741691
}
16751692
}
16761693
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
12+
13+
// compile-flags:-Z extra-debug-info
14+
// debugger:break zzz
15+
// debugger:run
16+
17+
// debugger:finish
18+
// debugger:print x
19+
// check:$1 = false
20+
// debugger:print y
21+
// check:$2 = true
22+
// debugger:continue
23+
24+
// debugger:finish
25+
// debugger:print x
26+
// check:$3 = 10
27+
// debugger:print y
28+
// check:$4 = true
29+
// debugger:continue
30+
31+
// debugger:finish
32+
// debugger:print x
33+
// check:$5 = 10.5
34+
// debugger:print y
35+
// check:$6 = 20
36+
// debugger:continue
37+
38+
fn a_function(x: bool, y: bool) {
39+
zzz();
40+
sentinel();
41+
42+
let x = 10;
43+
44+
zzz();
45+
sentinel();
46+
47+
let x = 10.5;
48+
let y = 20;
49+
50+
zzz();
51+
sentinel();
52+
}
53+
54+
fn main() {
55+
a_function(false, true);
56+
}
57+
58+
fn zzz() {()}
59+
fn sentinel() {()}

0 commit comments

Comments
 (0)