diff --git a/ChangeLog b/ChangeLog index 0e43e1df72..f093b8412d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Tue May 6 23:28:47 2014 Nobuyoshi Nakada + + * parse.y (local_tbl_gen): remove local variables duplicated with + arguments. + Tue May 6 18:48:50 2014 Tanaka Akira * lib/time.rb (Time.make_time): Adjust the time zone of "now". diff --git a/parse.y b/parse.y index 8fcbe3a2c0..888b12c75e 100644 --- a/parse.y +++ b/parse.y @@ -9714,31 +9714,26 @@ local_pop_gen(struct parser_params *parser) } #ifndef RIPPER -static ID* -vtable_tblcpy(ID *buf, const struct vtable *src) -{ - int i, cnt = vtable_size(src); - - if (cnt > 0) { - buf[0] = cnt; - for (i = 0; i < cnt; i++) { - buf[i] = src->tbl[i]; - } - return buf; - } - return 0; -} - static ID* local_tbl_gen(struct parser_params *parser) { - int cnt = vtable_size(lvtbl->args) + vtable_size(lvtbl->vars); + int cnt_args = vtable_size(lvtbl->args); + int cnt_vars = vtable_size(lvtbl->vars); + int cnt = cnt_args + cnt_vars; + int i, j; ID *buf; if (cnt <= 0) return 0; buf = ALLOC_N(ID, cnt + 1); - vtable_tblcpy(buf+1, lvtbl->args); - vtable_tblcpy(buf+vtable_size(lvtbl->args)+1, lvtbl->vars); + MEMCPY(buf+1, lvtbl->args->tbl, ID, cnt_args); + /* remove IDs duplicated to warn shadowing */ + for (i = 0, j = cnt_args+1; i < cnt_vars; ++i) { + ID id = lvtbl->vars->tbl[i]; + if (!vtable_included(lvtbl->args, id)) { + buf[j++] = id; + } + } + if (--j < cnt) REALLOC_N(buf, ID, (cnt = j) + 1); buf[0] = cnt; return buf; } diff --git a/test/ruby/test_variable.rb b/test/ruby/test_variable.rb index ab4d44938a..89f1d58348 100644 --- a/test/ruby/test_variable.rb +++ b/test/ruby/test_variable.rb @@ -83,6 +83,12 @@ class TestVariable < Test::Unit::TestCase end.call end + def test_shadowing_local_variables + bug9486 = '[ruby-core:60501] [Bug #9486]' + x = tap {|x| break local_variables} + assert_equal([:x, :bug9486, :x], x) + end + def local_variables_of(bind) this_should_not_be_in_bind = 2 bind.local_variables