diff --git a/ChangeLog b/ChangeLog index 4e95843439..d0bd96a5e8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Sun Jul 26 18:30:02 2009 Nobuyoshi Nakada + + * vm_insnhelper.c (vm_call_method): __send__ can call protected + methods. [ruby-core:24500] + Sun Jul 26 01:09:14 2009 Alexander Zavorine * ext/bigdecimal.c: moved BASE_FIG definition before it is used diff --git a/test/ruby/test_module.rb b/test/ruby/test_module.rb index 99b9849d98..066dd86011 100644 --- a/test/ruby/test_module.rb +++ b/test/ruby/test_module.rb @@ -104,12 +104,15 @@ class TestModule < Test::Unit::TestCase private_class_method :cm1, "cm3" def aClass + :aClass end def aClass1 + :aClass1 end def aClass2 + :aClass2 end private :aClass1 @@ -118,15 +121,18 @@ class TestModule < Test::Unit::TestCase class BClass < AClass def bClass1 + :bClass1 end private def bClass2 + :bClass2 end protected def bClass3 + :bClass3 end end @@ -489,7 +495,7 @@ class TestModule < Test::Unit::TestCase c = Class.new assert_raise(NameError) do - c.instance_eval { attr_reader :"$" } + c.instance_eval { attr_reader :"." } end end @@ -721,4 +727,18 @@ class TestModule < Test::Unit::TestCase }.call end end + + def test_send + a = AClass.new + assert_equal(:aClass, a.__send__(:aClass)) + assert_equal(:aClass1, a.__send__(:aClass1)) + assert_equal(:aClass2, a.__send__(:aClass2)) + b = BClass.new + assert_equal(:aClass, b.__send__(:aClass)) + assert_equal(:aClass1, b.__send__(:aClass1)) + assert_equal(:aClass2, b.__send__(:aClass2)) + assert_equal(:bClass1, b.__send__(:bClass1)) + assert_equal(:bClass2, b.__send__(:bClass2)) + assert_equal(:bClass3, b.__send__(:bClass3)) + end end diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 97ba1baba6..4e7ce63f84 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -496,6 +496,7 @@ vm_call_method(rb_thread_t *th, rb_control_frame_t *cfp, ID id, const rb_method_entry_t *me, VALUE recv) { VALUE val; + int opt_send = 0; start_method_dispatch: @@ -567,6 +568,7 @@ vm_call_method(rb_thread_t *th, rb_control_frame_t *cfp, num -= 1; DEC_SP(1); flag |= VM_CALL_FCALL_BIT; + opt_send = 1; goto start_method_dispatch; } @@ -605,7 +607,7 @@ vm_call_method(rb_thread_t *th, rb_control_frame_t *cfp, } val = vm_method_missing(th, id, recv, num, blockptr, stat); } - else if ((me->flag & NOEX_MASK) & NOEX_PROTECTED) { + else if (!opt_send && (me->flag & NOEX_MASK) & NOEX_PROTECTED) { VALUE defined_class = me->klass; if (TYPE(defined_class) == T_ICLASS) {