From 1e56548995fe2b3b266ccdfecce0ef1163534dc6 Mon Sep 17 00:00:00 2001 From: nobu Date: Tue, 25 Sep 2012 00:59:29 +0000 Subject: insns.def: super from at_exit * insns.def (invokesuper): klass in cfp is not valid in at_exit and END blocks. [ruby-core:47680] [Bug #7064] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37030 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 5 +++++ insns.def | 3 +++ test/ruby/test_super.rb | 11 +++++++++++ vm_insnhelper.c | 13 +++++++++---- 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 + + * 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 * 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 @@ -1459,6 +1459,12 @@ vm_search_normal_superclass(VALUE klass) return RCLASS_SUPER(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, @@ -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; -- cgit v1.2.3