summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-06-17 19:27:24 +0000
committerko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-06-17 19:27:24 +0000
commit00e4fd42f36fa23de04cccb9cea3c3e5d14c9ae9 (patch)
tree0012d083c6af5721147cdd7ed7d21d260f38b811
parente2f37fb9c6c9df54b2be78d09de00aa7da0d694f (diff)
* 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--ChangeLog7
-rw-r--r--KNOWNBUGS.rb21
-rw-r--r--bootstraptest/test_proc.rb88
-rw-r--r--vm.c4
-rw-r--r--vm_insnhelper.c28
5 files changed, 125 insertions, 23 deletions
diff --git a/ChangeLog b/ChangeLog
index 5ee8ec32c2..d6fad04f4c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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]'
diff --git a/vm.c b/vm.c
index bb1ba4cb59..83b6ea9bd4 100644
--- a/vm.c
+++ b/vm.c
@@ -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");