Skip to content

Commit f5f6218

Browse files
committed
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
1 parent ce59e24 commit f5f6218

3 files changed

Lines changed: 34 additions & 2 deletions

File tree

ChangeLog

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
Thu Dec 25 12:47:44 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
2+
3+
* parse.y (gettable_gen): warn possible reference to a local
4+
variable defined in a past scope.
5+
16
Thu Dec 25 10:09:14 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
27

38
* ext/io/console/console.c (console_dev): id_console is not a

parse.y

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ struct local_vars {
113113
struct vtable *args;
114114
struct vtable *vars;
115115
struct vtable *used;
116+
struct vtable *past;
116117
struct local_vars *prev;
117118
stack_type cmdargs;
118119
};
@@ -8827,6 +8828,17 @@ match_op_gen(struct parser_params *parser, NODE *node1, NODE *node2)
88278828
return NEW_CALL(node1, tMATCH, NEW_LIST(node2));
88288829
}
88298830

8831+
static int
8832+
past_dvar_p(struct parser_params *parser, ID id)
8833+
{
8834+
struct vtable *past = lvtbl->past;
8835+
while (past) {
8836+
if (vtable_included(past, id)) return 1;
8837+
past = past->prev;
8838+
}
8839+
return 0;
8840+
}
8841+
88308842
static NODE*
88318843
gettable_gen(struct parser_params *parser, ID id)
88328844
{
@@ -8860,6 +8872,9 @@ gettable_gen(struct parser_params *parser, ID id)
88608872
}
88618873
return NEW_LVAR(id);
88628874
}
8875+
if (!in_defined && RTEST(ruby_verbose) && past_dvar_p(parser, id)) {
8876+
rb_warningV("possible reference to past scope - %"PRIsVALUE, rb_id2str(id));
8877+
}
88638878
/* method call without arguments */
88648879
return NEW_VCALL(id);
88658880
case ID_GLOBAL:
@@ -9978,6 +9993,7 @@ local_push_gen(struct parser_params *parser, int inherit_dvars)
99789993
local->used = !(inherit_dvars &&
99799994
(ifndef_ripper(compile_for_eval || e_option_supplied(parser))+0)) &&
99809995
RTEST(ruby_verbose) ? vtable_alloc(0) : 0;
9996+
local->past = 0;
99819997
local->cmdargs = cmdarg_stack;
99829998
cmdarg_stack = 0;
99839999
lvtbl = local;
@@ -9991,6 +10007,11 @@ local_pop_gen(struct parser_params *parser)
999110007
warn_unused_var(parser, lvtbl);
999210008
vtable_free(lvtbl->used);
999310009
}
10010+
while (lvtbl->past) {
10011+
struct vtable *past = lvtbl->past;
10012+
lvtbl->past = past->prev;
10013+
vtable_free(past);
10014+
}
999410015
vtable_free(lvtbl->args);
999510016
vtable_free(lvtbl->vars);
999610017
cmdarg_stack = lvtbl->cmdargs;
@@ -10090,10 +10111,12 @@ dyna_pop_1(struct parser_params *parser)
1009010111
}
1009110112
tmp = lvtbl->args;
1009210113
lvtbl->args = lvtbl->args->prev;
10093-
vtable_free(tmp);
10114+
tmp->prev = lvtbl->past;
10115+
lvtbl->past = tmp;
1009410116
tmp = lvtbl->vars;
1009510117
lvtbl->vars = lvtbl->vars->prev;
10096-
vtable_free(tmp);
10118+
tmp->prev = lvtbl->past;
10119+
lvtbl->past = tmp;
1009710120
}
1009810121

1009910122
static void

test/ruby/test_parse.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -873,4 +873,8 @@ def test_named_capture_conflict
873873
a = "\u{3042}"
874874
assert_warning(/#{a}/) {eval("#{a} = 1; /(?<#{a}>)/ =~ ''")}
875875
end
876+
877+
def test_past_scope_variable
878+
assert_warning(/past scope/) {catch {|tag| eval("BEGIN{throw tag}; tap {a = 1}; a")}}
879+
end
876880
end

0 commit comments

Comments
 (0)