mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
parse.y: warn past scope variable
* parse.y (gettable_gen): warn possible reference to a local variable defined in a past scope. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@48986 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
ce59e249a5
commit
f5f6218a23
3 changed files with 34 additions and 2 deletions
|
@ -1,3 +1,8 @@
|
|||
Thu Dec 25 12:47:44 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||
|
||||
* 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@ruby-lang.org>
|
||||
|
||||
* ext/io/console/console.c (console_dev): id_console is not a
|
||||
|
|
27
parse.y
27
parse.y
|
@ -113,6 +113,7 @@ struct local_vars {
|
|||
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 *parser, NODE *node1, NODE *node2)
|
|||
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 *parser, ID id)
|
|||
}
|
||||
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 *parser, int inherit_dvars)
|
|||
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 *parser)
|
|||
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)
|
|||
}
|
||||
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
|
||||
|
|
|
@ -873,4 +873,8 @@ x = __ENCODING__
|
|||
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
|
||||
|
|
Loading…
Add table
Reference in a new issue