ruby-changes:58188
From: Nobuyoshi <ko1@a...>
Date: Thu, 10 Oct 2019 14:11:41 +0900 (JST)
Subject: [ruby-changes:58188] c2065c64cb (master): Fixed numbered parameter check
https://git.ruby-lang.org/ruby.git/commit/?id=c2065c64cb From c2065c64cb198d5b53a5ecdf9638d064f6fec2e2 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada <nobu@r...> Date: Thu, 10 Oct 2019 13:50:13 +0900 Subject: 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] diff --git a/parse.y b/parse.y index 72470af..f9de951 100644 --- a/parse.y +++ b/parse.y @@ -165,6 +165,11 @@ struct local_vars { https://github.com/ruby/ruby/blob/trunk/parse.y#L165 struct vtable *past; # endif struct local_vars *prev; +# ifndef RIPPER + struct { + NODE *outer, *inner, *current; + } numparam; +# endif }; enum { @@ -295,10 +300,6 @@ struct parser_params { https://github.com/ruby/ruby/blob/trunk/parse.y#L300 VALUE error_buffer; VALUE debug_lines; const struct rb_iseq_struct *parent_iseq; - - struct { - NODE *outer, *inner, *current; - } numparam; #else /* Ripper only */ @@ -9828,8 +9829,9 @@ past_dvar_p(struct parser_params *p, ID id) https://github.com/ruby/ruby/blob/trunk/parse.y#L9829 static int numparam_nested_p(struct parser_params *p) { - NODE *outer = p->numparam.outer; - NODE *inner = p->numparam.inner; + struct local_vars *local = p->lvtbl; + NODE *outer = local->numparam.outer; + NODE *inner = local->numparam.inner; if (outer || inner) { NODE *used = outer ? outer : inner; compile_error(p, "numbered parameter is already used in\n" @@ -9906,7 +9908,8 @@ gettable(struct parser_params *p, ID id, const YYLTYPE *loc) https://github.com/ruby/ruby/blob/trunk/parse.y#L9908 parser_numbered_param(p, NUMPARAM_ID_TO_IDX(id))) { if (numparam_nested_p(p)) return 0; 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; } # if WARN_PAST_SCOPE @@ -11660,6 +11663,9 @@ local_push(struct parser_params *p, int toplevel_scope) https://github.com/ruby/ruby/blob/trunk/parse.y#L11663 #ifndef RIPPER if (toplevel_scope && compile_for_eval) 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 local->used = warn_unused_vars ? vtable_alloc(0) : 0; @@ -11692,11 +11698,6 @@ local_pop(struct parser_params *p) https://github.com/ruby/ruby/blob/trunk/parse.y#L11698 COND_POP(); ruby_sized_xfree(p->lvtbl, sizeof(*p->lvtbl)); p->lvtbl = local; -# ifndef RIPPER - p->numparam.outer = 0; - p->numparam.inner = 0; - p->numparam.current = 0; -# endif } #ifndef RIPPER @@ -11803,12 +11804,13 @@ static NODE * https://github.com/ruby/ruby/blob/trunk/parse.y#L11804 numparam_push(struct parser_params *p) { #ifndef RIPPER - NODE *inner = p->numparam.inner; - if (!p->numparam.outer) { - p->numparam.outer = p->numparam.current; + struct local_vars *local = p->lvtbl; + NODE *inner = local->numparam.inner; + if (!local->numparam.outer) { + local->numparam.outer = local->numparam.current; } - p->numparam.inner = 0; - p->numparam.current = 0; + local->numparam.inner = 0; + local->numparam.current = 0; return inner; #else return 0; @@ -11819,22 +11821,23 @@ static void https://github.com/ruby/ruby/blob/trunk/parse.y#L11821 numparam_pop(struct parser_params *p, NODE *prev_inner) { #ifndef RIPPER + struct local_vars *local = p->lvtbl; if (prev_inner) { /* 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 */ - p->numparam.inner = p->numparam.current; + local->numparam.inner = local->numparam.current; } if (p->max_numparam > NO_PARAM) { /* current and outer are exclusive */ - p->numparam.current = p->numparam.outer; - p->numparam.outer = 0; + local->numparam.current = local->numparam.outer; + local->numparam.outer = 0; } else { /* no numbered parameter */ - p->numparam.current = 0; + local->numparam.current = 0; } #endif } diff --git a/test/ruby/test_syntax.rb b/test/ruby/test_syntax.rb index 80bff86..48610da 100644 --- a/test/ruby/test_syntax.rb +++ b/test/ruby/test_syntax.rb @@ -1465,6 +1465,10 @@ eom https://github.com/ruby/ruby/blob/trunk/test/ruby/test_syntax.rb#L1465 assert_syntax_error('-> {-> {_1}; _2}', /numbered parameter is already used/) assert_warn(/`_1' is used as numbered parameter/) {eval('proc {_1 = nil}')} 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 def test_value_expr_in_condition -- cgit v0.10.2 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/