mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Fixed numbered parameter check
* parse.y (struct local_vars): moved numbered parameter NODEs for nesting check to separate per local variable scopes, as numbered parameters should belong to local variable scopes. [Bug #16248]
This commit is contained in:
parent
a23b639050
commit
c2065c64cb
2 changed files with 30 additions and 23 deletions
49
parse.y
49
parse.y
|
@ -165,6 +165,11 @@ struct local_vars {
|
||||||
struct vtable *past;
|
struct vtable *past;
|
||||||
# endif
|
# endif
|
||||||
struct local_vars *prev;
|
struct local_vars *prev;
|
||||||
|
# ifndef RIPPER
|
||||||
|
struct {
|
||||||
|
NODE *outer, *inner, *current;
|
||||||
|
} numparam;
|
||||||
|
# endif
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
@ -295,10 +300,6 @@ struct parser_params {
|
||||||
VALUE error_buffer;
|
VALUE error_buffer;
|
||||||
VALUE debug_lines;
|
VALUE debug_lines;
|
||||||
const struct rb_iseq_struct *parent_iseq;
|
const struct rb_iseq_struct *parent_iseq;
|
||||||
|
|
||||||
struct {
|
|
||||||
NODE *outer, *inner, *current;
|
|
||||||
} numparam;
|
|
||||||
#else
|
#else
|
||||||
/* Ripper only */
|
/* Ripper only */
|
||||||
|
|
||||||
|
@ -9828,8 +9829,9 @@ past_dvar_p(struct parser_params *p, ID id)
|
||||||
static int
|
static int
|
||||||
numparam_nested_p(struct parser_params *p)
|
numparam_nested_p(struct parser_params *p)
|
||||||
{
|
{
|
||||||
NODE *outer = p->numparam.outer;
|
struct local_vars *local = p->lvtbl;
|
||||||
NODE *inner = p->numparam.inner;
|
NODE *outer = local->numparam.outer;
|
||||||
|
NODE *inner = local->numparam.inner;
|
||||||
if (outer || inner) {
|
if (outer || inner) {
|
||||||
NODE *used = outer ? outer : inner;
|
NODE *used = outer ? outer : inner;
|
||||||
compile_error(p, "numbered parameter is already used in\n"
|
compile_error(p, "numbered parameter is already used in\n"
|
||||||
|
@ -9906,7 +9908,8 @@ gettable(struct parser_params *p, ID id, const YYLTYPE *loc)
|
||||||
parser_numbered_param(p, NUMPARAM_ID_TO_IDX(id))) {
|
parser_numbered_param(p, NUMPARAM_ID_TO_IDX(id))) {
|
||||||
if (numparam_nested_p(p)) return 0;
|
if (numparam_nested_p(p)) return 0;
|
||||||
node = NEW_DVAR(id, loc);
|
node = NEW_DVAR(id, loc);
|
||||||
if (!p->numparam.current) p->numparam.current = node;
|
struct local_vars *local = p->lvtbl;
|
||||||
|
if (!local->numparam.current) local->numparam.current = node;
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
# if WARN_PAST_SCOPE
|
# if WARN_PAST_SCOPE
|
||||||
|
@ -11660,6 +11663,9 @@ local_push(struct parser_params *p, int toplevel_scope)
|
||||||
#ifndef RIPPER
|
#ifndef RIPPER
|
||||||
if (toplevel_scope && compile_for_eval) warn_unused_vars = 0;
|
if (toplevel_scope && compile_for_eval) warn_unused_vars = 0;
|
||||||
if (toplevel_scope && e_option_supplied(p)) warn_unused_vars = 0;
|
if (toplevel_scope && e_option_supplied(p)) warn_unused_vars = 0;
|
||||||
|
local->numparam.outer = 0;
|
||||||
|
local->numparam.inner = 0;
|
||||||
|
local->numparam.current = 0;
|
||||||
#endif
|
#endif
|
||||||
local->used = warn_unused_vars ? vtable_alloc(0) : 0;
|
local->used = warn_unused_vars ? vtable_alloc(0) : 0;
|
||||||
|
|
||||||
|
@ -11692,11 +11698,6 @@ local_pop(struct parser_params *p)
|
||||||
COND_POP();
|
COND_POP();
|
||||||
ruby_sized_xfree(p->lvtbl, sizeof(*p->lvtbl));
|
ruby_sized_xfree(p->lvtbl, sizeof(*p->lvtbl));
|
||||||
p->lvtbl = local;
|
p->lvtbl = local;
|
||||||
# ifndef RIPPER
|
|
||||||
p->numparam.outer = 0;
|
|
||||||
p->numparam.inner = 0;
|
|
||||||
p->numparam.current = 0;
|
|
||||||
# endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef RIPPER
|
#ifndef RIPPER
|
||||||
|
@ -11803,12 +11804,13 @@ static NODE *
|
||||||
numparam_push(struct parser_params *p)
|
numparam_push(struct parser_params *p)
|
||||||
{
|
{
|
||||||
#ifndef RIPPER
|
#ifndef RIPPER
|
||||||
NODE *inner = p->numparam.inner;
|
struct local_vars *local = p->lvtbl;
|
||||||
if (!p->numparam.outer) {
|
NODE *inner = local->numparam.inner;
|
||||||
p->numparam.outer = p->numparam.current;
|
if (!local->numparam.outer) {
|
||||||
|
local->numparam.outer = local->numparam.current;
|
||||||
}
|
}
|
||||||
p->numparam.inner = 0;
|
local->numparam.inner = 0;
|
||||||
p->numparam.current = 0;
|
local->numparam.current = 0;
|
||||||
return inner;
|
return inner;
|
||||||
#else
|
#else
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -11819,22 +11821,23 @@ static void
|
||||||
numparam_pop(struct parser_params *p, NODE *prev_inner)
|
numparam_pop(struct parser_params *p, NODE *prev_inner)
|
||||||
{
|
{
|
||||||
#ifndef RIPPER
|
#ifndef RIPPER
|
||||||
|
struct local_vars *local = p->lvtbl;
|
||||||
if (prev_inner) {
|
if (prev_inner) {
|
||||||
/* prefer first one */
|
/* prefer first one */
|
||||||
p->numparam.inner = prev_inner;
|
local->numparam.inner = prev_inner;
|
||||||
}
|
}
|
||||||
else if (p->numparam.current) {
|
else if (local->numparam.current) {
|
||||||
/* current and inner are exclusive */
|
/* current and inner are exclusive */
|
||||||
p->numparam.inner = p->numparam.current;
|
local->numparam.inner = local->numparam.current;
|
||||||
}
|
}
|
||||||
if (p->max_numparam > NO_PARAM) {
|
if (p->max_numparam > NO_PARAM) {
|
||||||
/* current and outer are exclusive */
|
/* current and outer are exclusive */
|
||||||
p->numparam.current = p->numparam.outer;
|
local->numparam.current = local->numparam.outer;
|
||||||
p->numparam.outer = 0;
|
local->numparam.outer = 0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* no numbered parameter */
|
/* no numbered parameter */
|
||||||
p->numparam.current = 0;
|
local->numparam.current = 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -1465,6 +1465,10 @@ eom
|
||||||
assert_syntax_error('-> {-> {_1}; _2}', /numbered parameter is already used/)
|
assert_syntax_error('-> {-> {_1}; _2}', /numbered parameter is already used/)
|
||||||
assert_warn(/`_1' is used as numbered parameter/) {eval('proc {_1 = nil}')}
|
assert_warn(/`_1' is used as numbered parameter/) {eval('proc {_1 = nil}')}
|
||||||
assert_warn(/`_2' is used as numbered parameter/) {eval('_2=1')}
|
assert_warn(/`_2' is used as numbered parameter/) {eval('_2=1')}
|
||||||
|
['class C', 'class << C', 'module M', 'def m', 'def o.m'].each do |c|
|
||||||
|
assert_valid_syntax("->{#{c};->{_1};end;_1}\n")
|
||||||
|
assert_valid_syntax("->{_1;#{c};->{_1};end}\n")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_value_expr_in_condition
|
def test_value_expr_in_condition
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue