about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorMichael Woerister <michaelwoerister@gmail>2013-08-07 00:13:31 +0200
committerMichael Woerister <michaelwoerister@gmail>2013-08-13 11:13:49 +0200
commit9c7d9eb6fdd3a14bbad65949d73a0d9b86f6ec33 (patch)
tree6f911e58dffa2e4adb279e881076cd3c6ea64d67 /src
parent33e7d95e9c4ff02b4fb949ea51a26a8bf5e9ae5c (diff)
downloadrust-9c7d9eb6fdd3a14bbad65949d73a0d9b86f6ec33.tar.gz
rust-9c7d9eb6fdd3a14bbad65949d73a0d9b86f6ec33.zip
debuginfo: Add support for argument shadowing.
Diffstat (limited to 'src')
-rw-r--r--src/librustc/middle/trans/common.rs2
-rw-r--r--src/librustc/middle/trans/debuginfo.rs85
-rw-r--r--src/test/debug-info/shadowed-argument.rs59
3 files changed, 110 insertions, 36 deletions
diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs
index 10185a9a795..9aa18bc05f8 100644
--- a/src/librustc/middle/trans/common.rs
+++ b/src/librustc/middle/trans/common.rs
@@ -230,8 +230,6 @@ pub struct FunctionContext {
     ccx: @mut CrateContext,
 
     // Used and maintained by the debuginfo module.
-    // @jdm: Not sure if the Option-wrapper is a good idea. It allows to save some space in
-    // non-debug builds, but generates quite a bit of noise at usage sites. What's your opinion?
     debug_context: Option<~debuginfo::FunctionDebugContext>
 }
 
diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs
index c315421a779..5591f7debf8 100644
--- a/src/librustc/middle/trans/debuginfo.rs
+++ b/src/librustc/middle/trans/debuginfo.rs
@@ -271,11 +271,11 @@ pub fn create_function_metadata(fcx: &mut FunctionContext) -> DISubprogram {
     let cx = fcx.ccx;
 
     let fnitem = cx.tcx.items.get_copy(&fcx.id);
-    let (ident, ret_ty, id) = match fnitem {
+    let (ident, fn_decl, id) = match fnitem {
         ast_map::node_item(ref item, _) => {
             match item.node {
-                ast::item_fn(ast::fn_decl { output: ref ty, _}, _, _, _, _) => {
-                    (item.ident, ty, item.id)
+                ast::item_fn(ref fn_decl, _, _, _, _) => {
+                    (item.ident, fn_decl, item.id)
                 }
                 _ => fcx.ccx.sess.span_bug(item.span,
                                            "create_function_metadata: item bound to non-function")
@@ -283,20 +283,20 @@ pub fn create_function_metadata(fcx: &mut FunctionContext) -> DISubprogram {
         }
         ast_map::node_method(
             @ast::method {
-                decl: ast::fn_decl { output: ref ty, _ },
+                decl: ref fn_decl,
                 id: id,
                 ident: ident,
                 _
             },
             _,
             _) => {
-            (ident, ty, id)
+            (ident, fn_decl, id)
         }
         ast_map::node_expr(ref expr) => {
             match expr.node {
-                ast::expr_fn_block(ref decl, _) => {
+                ast::expr_fn_block(ref fn_decl, _) => {
                     let name = gensym_name("fn");
-                    (name, &decl.output, expr.id)
+                    (name, fn_decl, expr.id)
                 }
                 _ => fcx.ccx.sess.span_bug(expr.span,
                         "create_function_metadata: expected an expr_fn_block here")
@@ -305,14 +305,14 @@ pub fn create_function_metadata(fcx: &mut FunctionContext) -> DISubprogram {
         ast_map::node_trait_method(
             @ast::provided(
                 @ast::method {
-                    decl: ast::fn_decl { output: ref ty, _ },
+                    decl: ref fn_decl,
                     id: id,
                     ident: ident,
                     _
                 }),
             _,
             _) => {
-            (ident, ty, id)
+            (ident, fn_decl, id)
         }
         _ => fcx.ccx.sess.bug(fmt!("create_function_metadata: unexpected sort of node: %?", fnitem))
     };
@@ -335,9 +335,9 @@ pub fn create_function_metadata(fcx: &mut FunctionContext) -> DISubprogram {
     let file_metadata = file_metadata(cx, loc.file.name);
 
     let return_type_metadata = if cx.sess.opts.extra_debuginfo {
-        match ret_ty.node {
+        match fn_decl.output.node {
           ast::ty_nil => ptr::null(),
-          _ => type_metadata(cx, ty::node_id_to_type(cx.tcx, id), ret_ty.span)
+          _ => type_metadata(cx, ty::node_id_to_type(cx.tcx, id), fn_decl.output.span)
         }
     } else {
         ptr::null()
@@ -382,7 +382,9 @@ pub fn create_function_metadata(fcx: &mut FunctionContext) -> DISubprogram {
     match *entry_block {
         ast_map::node_block(ref block) => {
             let scope_map = &mut fn_debug_context.scope_map;
-            populate_scope_map(cx, block, fn_metadata, scope_map);
+            let arg_pats = do fn_decl.inputs.map |arg_ref| { arg_ref.pat };
+
+            populate_scope_map(cx, arg_pats, block, fn_metadata, scope_map);
         }
         _ => cx.sess.span_bug(span,
                 fmt!("debuginfo::create_function_metadata() - \
@@ -1278,9 +1280,11 @@ fn DIB(cx: &CrateContext) -> DIBuilderRef {
 // descriptors where necessary. These artificial scopes allow GDB to correctly handle name
 // shadowing.
 fn populate_scope_map(cx: &mut CrateContext,
+                      arg_pats: &[@ast::pat],
                       fn_entry_block: &ast::Block,
                       fn_metadata: DISubprogram,
                       scope_map: &mut HashMap<ast::NodeId, DIScope>) {
+    let def_map = cx.tcx.def_map;
 
     struct ScopeStackEntry {
         scope_metadata: DIScope,
@@ -1289,6 +1293,15 @@ fn populate_scope_map(cx: &mut CrateContext,
 
     let mut scope_stack = ~[ScopeStackEntry { scope_metadata: fn_metadata, ident: None }];
 
+    // Push argument identifiers onto the stack so arguments integrate nicely with variable
+    // shadowing.
+    for &arg_pat in arg_pats.iter() {
+        do pat_util::pat_bindings(def_map, arg_pat) |_, _, _, path_ref| {
+            let ident = ast_util::path_to_ident(path_ref);
+            scope_stack.push(ScopeStackEntry { scope_metadata: fn_metadata, ident: Some(ident) });
+        }
+    }
+
     walk_block(cx, fn_entry_block, &mut scope_stack, scope_map);
 
     // local helper functions for walking the AST.
@@ -1300,7 +1313,6 @@ fn populate_scope_map(cx: &mut CrateContext,
                       inner_walk: &fn(&mut CrateContext,
                                       &mut ~[ScopeStackEntry],
                                       &mut HashMap<ast::NodeId, DIScope>)) {
-
         // Create a new lexical scope and push it onto the stack
         let loc = cx.sess.codemap.lookup_char_pos(scope_span.lo);
         let file_metadata = file_metadata(cx, loc.file.name);
@@ -1335,7 +1347,6 @@ fn populate_scope_map(cx: &mut CrateContext,
                   block: &ast::Block,
                   scope_stack: &mut ~[ScopeStackEntry],
                   scope_map: &mut HashMap<ast::NodeId, DIScope>) {
-
         scope_map.insert(block.id, scope_stack.last().scope_metadata);
 
         // The interesting things here are statements and the concluding expression.
@@ -1361,7 +1372,6 @@ fn populate_scope_map(cx: &mut CrateContext,
                  scope_map: &mut HashMap<ast::NodeId, DIScope>) {
         match *decl {
             codemap::spanned { node: ast::decl_local(@ref local), _ } => {
-
                 scope_map.insert(local.id, scope_stack.last().scope_metadata);
 
                 walk_pattern(cx, local.pat, scope_stack, scope_map);
@@ -1383,7 +1393,7 @@ fn populate_scope_map(cx: &mut CrateContext,
 
         // Unfortunately, we cannot just use pat_util::pat_bindings() or ast_util::walk_pat() here
         // because we have to visit *all* nodes in order to put them into the scope map. The above
-        // function don't do that.
+        // functions don't do that.
         match pat.node {
             ast::pat_ident(_, ref path_ref, ref sub_pat_opt) => {
 
@@ -1412,9 +1422,8 @@ fn populate_scope_map(cx: &mut CrateContext,
 
                     // Is there already a binding with that name?
                     let need_new_scope = scope_stack
-                        .rev_iter()
-                        .find_(|entry| entry.ident.iter().any(|i| *i == ident))
-                        .is_some();
+                        .iter()
+                        .any(|entry| entry.ident.iter().any(|i| *i == ident));
 
                     if need_new_scope {
                         // Create a new lexical scope and push it onto the stack
@@ -1574,8 +1583,10 @@ fn populate_scope_map(cx: &mut CrateContext,
             ast::expr_if(@ref cond_exp, ref then_block, ref opt_else_exp) => {
                 walk_expr(cx, cond_exp, scope_stack, scope_map);
 
-                do with_new_scope(cx, then_block.span, scope_stack, scope_map) |c, s, m| {
-                    walk_block(c, then_block, s, m);
+                do with_new_scope(cx, then_block.span, scope_stack, scope_map) |cx,
+                                                                                scope_stack,
+                                                                                scope_map| {
+                    walk_block(cx, then_block, scope_stack, scope_map);
                 }
 
                 match *opt_else_exp {
@@ -1587,8 +1598,10 @@ fn populate_scope_map(cx: &mut CrateContext,
             ast::expr_while(@ref cond_exp, ref loop_body) => {
                 walk_expr(cx, cond_exp, scope_stack, scope_map);
 
-                do with_new_scope(cx, loop_body.span, scope_stack, scope_map) |c, s, m| {
-                    walk_block(c, loop_body, s, m);
+                do with_new_scope(cx, loop_body.span, scope_stack, scope_map) |cx,
+                                                                               scope_stack,
+                                                                               scope_map| {
+                    walk_block(cx, loop_body, scope_stack, scope_map);
                 }
             }
 
@@ -1604,20 +1617,22 @@ fn populate_scope_map(cx: &mut CrateContext,
 
             ast::expr_loop(ref block, _) |
             ast::expr_block(ref block)   => {
-                do with_new_scope(cx, block.span, scope_stack, scope_map) |c, s, m| {
-                    walk_block(c, block, s, m);
+                do with_new_scope(cx, block.span, scope_stack, scope_map) |cx,
+                                                                           scope_stack,
+                                                                           scope_map| {
+                    walk_block(cx, block, scope_stack, scope_map);
                 }
             }
 
             ast::expr_fn_block(ast::fn_decl { inputs: ref inputs, _ }, ref block) => {
-
-                do with_new_scope(cx, block.span, scope_stack, scope_map) |c, s, m| {
-
+                do with_new_scope(cx, block.span, scope_stack, scope_map) |cx,
+                                                                           scope_stack,
+                                                                           scope_map| {
                     for &ast::arg { pat: pattern, _ } in inputs.iter() {
-                        walk_pattern(c, pattern, s, m);
+                        walk_pattern(cx, pattern, scope_stack, scope_map);
                     }
 
-                    walk_block(c, block, s, m);
+                    walk_block(cx, block, scope_stack, scope_map);
                 }
             }
 
@@ -1663,14 +1678,16 @@ fn populate_scope_map(cx: &mut CrateContext,
                 for arm_ref in arms.iter() {
                     let arm_span = arm_ref.pats[0].span;
 
-                    do with_new_scope(cx, arm_span, scope_stack, scope_map) |c, s, m| {
-                        walk_pattern(c, arm_ref.pats[0], s, m);
+                    do with_new_scope(cx, arm_span, scope_stack, scope_map) |cx,
+                                                                             scope_stack,
+                                                                             scope_map| {
+                        walk_pattern(cx, arm_ref.pats[0], scope_stack, scope_map);
 
                         for &@ref guard_exp in arm_ref.guard.iter() {
-                            walk_expr(c, guard_exp, s, m)
+                            walk_expr(cx, guard_exp, scope_stack, scope_map)
                         }
 
-                        walk_block(c, &arm_ref.body, s, m);
+                        walk_block(cx, &arm_ref.body, scope_stack, scope_map);
                     }
                 }
             }
diff --git a/src/test/debug-info/shadowed-argument.rs b/src/test/debug-info/shadowed-argument.rs
new file mode 100644
index 00000000000..b79b65c5f80
--- /dev/null
+++ b/src/test/debug-info/shadowed-argument.rs
@@ -0,0 +1,59 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
+
+// compile-flags:-Z extra-debug-info
+// debugger:break zzz
+// debugger:run
+
+// debugger:finish
+// debugger:print x
+// check:$1 = false
+// debugger:print y
+// check:$2 = true
+// debugger:continue
+
+// debugger:finish
+// debugger:print x
+// check:$3 = 10
+// debugger:print y
+// check:$4 = true
+// debugger:continue
+
+// debugger:finish
+// debugger:print x
+// check:$5 = 10.5
+// debugger:print y
+// check:$6 = 20
+// debugger:continue
+
+fn a_function(x: bool, y: bool) {
+    zzz();
+    sentinel();
+
+    let x = 10;
+
+    zzz();
+    sentinel();
+
+    let x = 10.5;
+    let y = 20;
+
+    zzz();
+    sentinel();
+}
+
+fn main() {
+    a_function(false, true);
+}
+
+fn zzz() {()}
+fn sentinel() {()}