diff options
author | ko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2008-06-17 19:27:24 +0000 |
---|---|---|
committer | ko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2008-06-17 19:27:24 +0000 |
commit | 00e4fd42f36fa23de04cccb9cea3c3e5d14c9ae9 (patch) | |
tree | 0012d083c6af5721147cdd7ed7d21d260f38b811 | |
parent | e2f37fb9c6c9df54b2be78d09de00aa7da0d694f (diff) | |
download | ruby-00e4fd42f36fa23de04cccb9cea3c3e5d14c9ae9.tar.gz |
* vm.c, vm_insnhelper.c: fix escape process with "braek" and "return"
syntax in "lambda". [ ruby-Bugs-19304 ], [ruby-core:17164]
* KNOWNBUGS.rb, bootstraptest/test_proc.rb: add/move solved test.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@17390 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 7 | ||||
-rw-r--r-- | KNOWNBUGS.rb | 21 | ||||
-rw-r--r-- | bootstraptest/test_proc.rb | 88 | ||||
-rw-r--r-- | vm.c | 4 | ||||
-rw-r--r-- | vm_insnhelper.c | 28 |
5 files changed, 125 insertions, 23 deletions
@@ -1,3 +1,10 @@ +Wed Jun 18 04:24:20 2008 Koichi Sasada <ko1@atdot.net> + + * vm.c, vm_insnhelper.c: fix escape process with "braek" and "return" + syntax in "lambda". [ ruby-Bugs-19304 ], [ruby-core:17164] + + * KNOWNBUGS.rb, bootstraptest/test_proc.rb: add/move solved test. + Wed Jun 18 01:51:10 2008 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> * ext/tk/lib/multi-tk.rb: cannot access class variable from diff --git a/KNOWNBUGS.rb b/KNOWNBUGS.rb index 7f6fa9274a..e3ac86776d 100644 --- a/KNOWNBUGS.rb +++ b/KNOWNBUGS.rb @@ -3,15 +3,18 @@ # So all tests will cause failure. # -assert_equal %q{[:bar, :foo]}, %q{ - def foo - klass = Class.new do - define_method(:bar) do - return :bar - end +assert_equal 'A', %q{ + class A + @@a = 'A' + def a=(x) + @@a = x + end + def a + @@a end - [klass.new.bar, :foo] end - foo -}, "[ ruby-Bugs-19304 ]" + B = A.dup + B.new.a = 'B' + A.new.a +} diff --git a/bootstraptest/test_proc.rb b/bootstraptest/test_proc.rb index 51c69448c8..1ffd5c08ac 100644 --- a/bootstraptest/test_proc.rb +++ b/bootstraptest/test_proc.rb @@ -276,3 +276,91 @@ assert_equal 'ok', %q{ :ng }.call }, '[ruby-dev:34646]' + +assert_equal %q{[:bar, :foo]}, %q{ + def foo + klass = Class.new do + define_method(:bar) do + return :bar + end + end + [klass.new.bar, :foo] + end + foo +}, "[ ruby-Bugs-19304 ]" + +assert_equal 'ok', %q{ + $x = :ok + def def7(x, y) + x[y] + $x = :ng + end + def test_def7 + def7(lambda {|x| x.call}, Proc.new {return}) + $x = :ng + end + test_def7 + $x +}, '[ruby-core:17164]' + +assert_equal 'ok', %q{ + lambda { a = lambda { return }; $x = :ng; a[]; $x = :ok }.call + $x +}, '[ruby-core:17164]' + +assert_equal 'ok', %q{ + lambda { a = lambda { break }; $x = :ng; a[]; $x = :ok }.call + $x +}, '[ruby-core:17164]' + +assert_equal 'ok', %q{ + def def8 + $x = :ng + lambda { a = Proc.new { return }; a[]}.call + $x = :ok + end + def8 + $x +}, '[ruby-core:17164]' + + +assert_equal 'ok', %q{ + def def9 + lambda {|a| $x = :ok; a[]; $x = :ng }.call(Proc.new { return }) + $x = :ng + end + def9 + $x +}, '[ruby-core:17164]' + +assert_equal 'ok', %q{ + def def10 + $x = :ng + lambda { 1.times { return } }.call + $x = :ok + end + $x = :ok + def10 + $x +}, '[ruby-core:17164]' + +assert_equal 'ok', %q{ + def def11 + yield + end + begin + lambda { def11 { return } }.call + rescue LocalJumpError + :ng + else + :ok + end +}, '[ruby-core:17164]' + +assert_equal 'ok', %q{ + def def12 + b = Proc.new { $x = :ng; lambda { return }.call; $x = :ok }.call + end + def12 + $x +}, '[ruby-core:17164]' @@ -525,9 +525,9 @@ vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, VALUE self, if (state == TAG_RETURN && proc->is_lambda) { VALUE err = th->errinfo; VALUE *escape_dfp = GET_THROWOBJ_CATCH_POINT(err); - VALUE *cdfp = proc->block.dfp; - if (escape_dfp == cdfp) { + if (escape_dfp == cfp->dfp) { + printf("ok\n"); state = 0; th->errinfo = Qnil; th->cfp = cfp; diff --git a/vm_insnhelper.c b/vm_insnhelper.c index cf3bd07220..864801be97 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -1044,7 +1044,8 @@ vm_get_cvar_base(NODE *cref) { VALUE klass; - while (cref && cref->nd_next && (NIL_P(cref->nd_clss) || FL_TEST(cref->nd_clss, FL_SINGLETON))) { + while (cref && cref->nd_next && + (NIL_P(cref->nd_clss) || FL_TEST(cref->nd_clss, FL_SINGLETON))) { cref = cref->nd_next; if (!cref->nd_next) { @@ -1221,7 +1222,7 @@ vm_throw(rb_thread_t *th, rb_control_frame_t *reg_cfp, if (cfp->dfp == dfp) { goto search_parent; } - cfp++; + cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); } rb_bug("VM (throw): can't find break base."); } @@ -1229,7 +1230,7 @@ vm_throw(rb_thread_t *th, rb_control_frame_t *reg_cfp, if (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_LAMBDA) { /* lambda{... break ...} */ is_orphan = 0; - pt = GET_LFP(); + pt = cfp->dfp; state = TAG_RETURN; } else { @@ -1261,7 +1262,7 @@ vm_throw(rb_thread_t *th, rb_control_frame_t *reg_cfp, is_orphan = 0; break; } - cfp++; + cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); } } @@ -1284,26 +1285,29 @@ vm_throw(rb_thread_t *th, rb_control_frame_t *reg_cfp, * check orphan: */ while ((VALUE *) cfp < th->stack + th->stack_size) { - if (GET_DFP() == dfp) { + if (dfp == cfp->dfp) { if (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_LAMBDA) { /* in lambda */ is_orphan = 0; break; } + + if (GET_LFP() == dfp && cfp->iseq->type == ISEQ_TYPE_METHOD) { + is_orphan = 0; + break; + } + + dfp = GC_GUARDED_PTR_REF(dfp[0]); } - if (GET_LFP() == cfp->lfp && - cfp->iseq->type == ISEQ_TYPE_METHOD) { - is_orphan = 0; - break; - } - cfp++; + + cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); } if (is_orphan) { vm_localjump_error("unexpected return", throwobj, TAG_RETURN); } - pt = GET_LFP(); + pt = dfp; } else { rb_bug("isns(throw): unsupport throw type"); |