Skip to content

Commit

Permalink
parse.y: warn past scope variable
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
nobu committed Dec 25, 2014
1 parent ce59e24 commit f5f6218
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 2 deletions.
5 changes: 5 additions & 0 deletions ChangeLog
@@ -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
Expand Down
27 changes: 25 additions & 2 deletions parse.y
Expand Up @@ -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;
};
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions test/ruby/test_parse.rb
Expand Up @@ -873,4 +873,8 @@ def test_named_capture_conflict
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

0 comments on commit f5f6218

Please sign in to comment.