ruby-changes:36905
From: nobu <ko1@a...>
Date: Thu, 25 Dec 2014 12:47:57 +0900 (JST)
Subject: [ruby-changes:36905] nobu:r48986 (trunk): parse.y: warn past scope variable
nobu 2014-12-25 12:47:46 +0900 (Thu, 25 Dec 2014) New Revision: 48986 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=48986 Log: parse.y: warn past scope variable * parse.y (gettable_gen): warn possible reference to a local variable defined in a past scope. Modified files: trunk/ChangeLog trunk/parse.y trunk/test/ruby/test_parse.rb Index: ChangeLog =================================================================== --- ChangeLog (revision 48985) +++ ChangeLog (revision 48986) @@ -1,3 +1,8 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Thu Dec 25 12:47:44 2014 Nobuyoshi Nakada <nobu@r...> + + * parse.y (gettable_gen): warn possible reference to a local + variable defined in a past scope. + Thu Dec 25 10:09:14 2014 Nobuyoshi Nakada <nobu@r...> * ext/io/console/console.c (console_dev): id_console is not a Index: parse.y =================================================================== --- parse.y (revision 48985) +++ parse.y (revision 48986) @@ -113,6 +113,7 @@ struct local_vars { https://github.com/ruby/ruby/blob/trunk/parse.y#L113 struct vtable *args; struct vtable *vars; struct vtable *used; + struct vtable *past; struct local_vars *prev; stack_type cmdargs; }; @@ -8827,6 +8828,17 @@ match_op_gen(struct parser_params *parse https://github.com/ruby/ruby/blob/trunk/parse.y#L8828 return NEW_CALL(node1, tMATCH, NEW_LIST(node2)); } +static int +past_dvar_p(struct parser_params *parser, ID id) +{ + struct vtable *past = lvtbl->past; + while (past) { + if (vtable_included(past, id)) return 1; + past = past->prev; + } + return 0; +} + static NODE* gettable_gen(struct parser_params *parser, ID id) { @@ -8860,6 +8872,9 @@ gettable_gen(struct parser_params *parse https://github.com/ruby/ruby/blob/trunk/parse.y#L8872 } return NEW_LVAR(id); } + if (!in_defined && RTEST(ruby_verbose) && past_dvar_p(parser, id)) { + rb_warningV("possible reference to past scope - %"PRIsVALUE, rb_id2str(id)); + } /* method call without arguments */ return NEW_VCALL(id); case ID_GLOBAL: @@ -9978,6 +9993,7 @@ local_push_gen(struct parser_params *par https://github.com/ruby/ruby/blob/trunk/parse.y#L9993 local->used = !(inherit_dvars && (ifndef_ripper(compile_for_eval || e_option_supplied(parser))+0)) && RTEST(ruby_verbose) ? vtable_alloc(0) : 0; + local->past = 0; local->cmdargs = cmdarg_stack; cmdarg_stack = 0; lvtbl = local; @@ -9991,6 +10007,11 @@ local_pop_gen(struct parser_params *pars https://github.com/ruby/ruby/blob/trunk/parse.y#L10007 warn_unused_var(parser, lvtbl); vtable_free(lvtbl->used); } + while (lvtbl->past) { + struct vtable *past = lvtbl->past; + lvtbl->past = past->prev; + vtable_free(past); + } vtable_free(lvtbl->args); vtable_free(lvtbl->vars); cmdarg_stack = lvtbl->cmdargs; @@ -10090,10 +10111,12 @@ dyna_pop_1(struct parser_params *parser) https://github.com/ruby/ruby/blob/trunk/parse.y#L10111 } tmp = lvtbl->args; lvtbl->args = lvtbl->args->prev; - vtable_free(tmp); + tmp->prev = lvtbl->past; + lvtbl->past = tmp; tmp = lvtbl->vars; lvtbl->vars = lvtbl->vars->prev; - vtable_free(tmp); + tmp->prev = lvtbl->past; + lvtbl->past = tmp; } static void Index: test/ruby/test_parse.rb =================================================================== --- test/ruby/test_parse.rb (revision 48985) +++ test/ruby/test_parse.rb (revision 48986) @@ -873,4 +873,8 @@ x = __ENCODING__ https://github.com/ruby/ruby/blob/trunk/test/ruby/test_parse.rb#L873 a = "\u{3042}" assert_warning(/#{a}/) {eval("#{a} = 1; /(?<#{a}>)/ =~ ''")} end + + def test_past_scope_variable + assert_warning(/past scope/) {catch {|tag| eval("BEGIN{throw tag}; tap {a = 1}; a")}} + end end -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/