[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]