aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--insns.def3
-rw-r--r--test/ruby/test_super.rb11
-rw-r--r--vm_insnhelper.c13
4 files changed, 28 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog
index 056ecfb727..38dec62e52 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Tue Sep 25 09:59:26 2012 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * insns.def (invokesuper): klass in cfp is not valid in at_exit and
+ END blocks. [ruby-core:47680] [Bug #7064]
+
Tue Sep 25 08:11:11 2012 NARUSE, Yui <naruse@ruby-lang.org>
* iseq.c (rb_iseq_defined_string): the index of defined_strings must
diff --git a/insns.def b/insns.def
index 94e1a24203..a1b8756d17 100644
--- a/insns.def
+++ b/insns.def
@@ -1035,6 +1035,9 @@ invokesuper
flag = VM_CALL_SUPER_BIT | VM_CALL_FCALL_BIT;
klass = GET_CFP()->klass;
+ if (NIL_P(klass)) {
+ vm_super_outside();
+ }
if (!NIL_P(RCLASS_REFINED_CLASS(klass))) {
klass = RCLASS_REFINED_CLASS(klass);
}
diff --git a/test/ruby/test_super.rb b/test/ruby/test_super.rb
index dcd700858c..bdd584c0b8 100644
--- a/test/ruby/test_super.rb
+++ b/test/ruby/test_super.rb
@@ -1,4 +1,5 @@
require 'test/unit'
+require_relative 'envutil'
class TestSuper < Test::Unit::TestCase
class Base
@@ -347,4 +348,14 @@ class TestSuper < Test::Unit::TestCase
assert_equal 'hoge', foo.new.bar
end
+
+ def test_super_in_at_exit
+ bug7064 = '[ruby-core:47680]'
+ assert_normal_exit "at_exit {super}", bug7064
+ end
+
+ def test_super_in_END
+ bug7064 = '[ruby-core:47680]'
+ assert_normal_exit "END {super}", bug7064
+ end
end
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index f6125c734d..46ef7e1a1c 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -1460,6 +1460,12 @@ vm_search_normal_superclass(VALUE klass)
}
static void
+vm_super_outside(void)
+{
+ rb_raise(rb_eNoMethodError, "super called outside of method");
+}
+
+static void
vm_search_superclass(rb_control_frame_t *reg_cfp, rb_iseq_t *iseq,
VALUE sigval,
ID *idp, VALUE *klassp)
@@ -1472,7 +1478,7 @@ vm_search_superclass(rb_control_frame_t *reg_cfp, rb_iseq_t *iseq,
}
if (iseq == 0) {
- rb_raise(rb_eNoMethodError, "super called outside of method");
+ vm_super_outside();
}
id = iseq->defined_method_id;
@@ -1492,8 +1498,7 @@ vm_search_superclass(rb_control_frame_t *reg_cfp, rb_iseq_t *iseq,
while (1) {
lcfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(lcfp);
if (RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, lcfp)) {
- rb_raise(rb_eNoMethodError,
- "super called outside of method");
+ vm_super_outside();
}
if (lcfp->ep == tep) {
break;
@@ -1503,7 +1508,7 @@ vm_search_superclass(rb_control_frame_t *reg_cfp, rb_iseq_t *iseq,
/* temporary measure for [Bug #2420] [Bug #3136] */
if (!lcfp->me) {
- rb_raise(rb_eNoMethodError, "super called outside of method");
+ vm_super_outside();
}
id = lcfp->me->def->original_id;