diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2012-08-20 11:36:34 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2012-08-20 11:36:34 +0000 |
commit | ceece4650a1de6189f2705cbf8120f6679a1af8f (patch) | |
tree | a229595768c98c125e260ab1faabda9370807712 | |
parent | de83cb9b20f2fa6ee6bace04ff29462cedd02a6d (diff) |
vm_insnhelper.c: iclass as klass in cfp
* vm_insnhelper.c (vm_call_method): follow iclasses as klass in cfp
but not included modules. [ruby-core:47241] [Bug #6891]
* vm_insnhelper.c (vm_call_bmethod): pass defined_class to follow
proper ancestors. [ruby-core:47241] [Bug #6891]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@36736 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 16 | ||||
-rw-r--r-- | cont.c | 2 | ||||
-rw-r--r-- | proc.c | 8 | ||||
-rw-r--r-- | test/ruby/test_module.rb | 54 | ||||
-rw-r--r-- | thread.c | 2 | ||||
-rw-r--r-- | vm.c | 32 | ||||
-rw-r--r-- | vm_core.h | 2 | ||||
-rw-r--r-- | vm_eval.c | 2 | ||||
-rw-r--r-- | vm_insnhelper.c | 8 |
9 files changed, 103 insertions, 23 deletions
@@ -1,3 +1,19 @@ +Mon Aug 20 20:36:30 2012 Nobuyoshi Nakada <nobu@ruby-lang.org> + + * vm_insnhelper.c (vm_call_method): follow iclasses as klass in cfp + but not included modules. [ruby-core:47241] [Bug #6891] + + * vm_insnhelper.c (vm_call_bmethod): pass defined_class to follow + proper ancestors. [ruby-core:47241] [Bug #6891] + +Mon Aug 20 20:36:13 2012 Nobuyoshi Nakada <nobu@ruby-lang.org> + + * vm_insnhelper.c (vm_call_method): follow iclasses as klass in cfp + but not included modules. [ruby-core:47241] [Bug #6891] + + * vm_insnhelper.c (vm_call_bmethod): pass defined_class to follow + proper ancestors. [ruby-core:47241] [Bug #6891] + Mon Aug 20 11:40:27 2012 Kazuhiro NISHIYAMA <zn@mbf.nifty.com> * common.mk: fix failed to make with -j2. @@ -1161,7 +1161,7 @@ rb_fiber_start(void) th->root_svar = Qnil; fib->status = RUNNING; - cont->value = rb_vm_invoke_proc(th, proc, proc->block.self, argc, argv, 0); + cont->value = rb_vm_invoke_proc(th, proc, argc, argv, 0); } TH_POP_TAG(); @@ -558,8 +558,7 @@ proc_call(int argc, VALUE *argv, VALUE procval) } } - vret = rb_vm_invoke_proc(GET_THREAD(), proc, proc->block.self, - argc, argv, blockptr); + vret = rb_vm_invoke_proc(GET_THREAD(), proc, argc, argv, blockptr); RB_GC_GUARD(procval); return vret; } @@ -584,7 +583,7 @@ rb_proc_call(VALUE self, VALUE args) VALUE vret; rb_proc_t *proc; GetProcPtr(self, proc); - vret = rb_vm_invoke_proc(GET_THREAD(), proc, proc->block.self, + vret = rb_vm_invoke_proc(GET_THREAD(), proc, check_argc(RARRAY_LEN(args)), RARRAY_PTR(args), 0); RB_GC_GUARD(self); RB_GC_GUARD(args); @@ -605,8 +604,7 @@ rb_proc_call_with_block(VALUE self, int argc, VALUE *argv, VALUE pass_procval) block = &pass_proc->block; } - vret = rb_vm_invoke_proc(GET_THREAD(), proc, proc->block.self, - argc, argv, block); + vret = rb_vm_invoke_proc(GET_THREAD(), proc, argc, argv, block); RB_GC_GUARD(self); RB_GC_GUARD(pass_procval); return vret; diff --git a/test/ruby/test_module.rb b/test/ruby/test_module.rb index 948ab53ed2..edcc388c8f 100644 --- a/test/ruby/test_module.rb +++ b/test/ruby/test_module.rb @@ -1398,4 +1398,58 @@ class TestModule < Test::Unit::TestCase assert_equal([:@@bar, :@@foo], m2.class_variables(true)) assert_equal([:@@bar], m2.class_variables(false)) end + + Bug6891 = '[ruby-core:47241]' + + def test_extend_module_with_protected_method + list = [] + + x = Class.new { + @list = list + + extend Module.new { + protected + + def inherited(klass) + @list << "protected" + super(klass) + end + } + + extend Module.new { + def inherited(klass) + @list << "public" + super(klass) + end + } + } + + assert_nothing_raised(NoMethodError, Bug6891) {Class.new(x)} + assert_equal(['public', 'protected'], list) + end + + def test_extend_module_with_protected_bmethod + list = [] + + x = Class.new { + extend Module.new { + protected + + define_method(:inherited) do |klass| + list << "protected" + super(klass) + end + } + + extend Module.new { + define_method(:inherited) do |klass| + list << "public" + super(klass) + end + } + } + + assert_nothing_raised(NoMethodError, Bug6891) {Class.new(x)} + assert_equal(['public', 'protected'], list) + end end @@ -455,7 +455,7 @@ thread_start_func_2(rb_thread_t *th, VALUE *stack_start, VALUE *register_stack_s th->errinfo = Qnil; th->root_lep = rb_vm_ep_local_ep(proc->block.ep); th->root_svar = Qnil; - th->value = rb_vm_invoke_proc(th, proc, proc->block.self, + th->value = rb_vm_invoke_proc(th, proc, (int)RARRAY_LEN(args), RARRAY_PTR(args), 0); } else { @@ -61,6 +61,10 @@ rb_vm_control_frame_block_ptr(rb_control_frame_t *cfp) return VM_CF_BLOCK_PTR(cfp); } +static VALUE +vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, VALUE self, VALUE defined_class, + int argc, const VALUE *argv, const rb_block_t *blockptr); + #include "vm_insnhelper.h" #include "vm_insnhelper.c" #include "vm_exec.h" @@ -577,7 +581,8 @@ rb_vm_make_proc(rb_thread_t *th, const rb_block_t *block, VALUE klass) static inline VALUE invoke_block_from_c(rb_thread_t *th, const rb_block_t *block, VALUE self, int argc, const VALUE *argv, - const rb_block_t *blockptr, const NODE *cref) + const rb_block_t *blockptr, const NODE *cref, + VALUE defined_class) { if (SPECIAL_CONST_P(block->iseq)) return Qnil; @@ -599,7 +604,7 @@ invoke_block_from_c(rb_thread_t *th, const rb_block_t *block, type == VM_FRAME_MAGIC_LAMBDA); vm_push_frame(th, iseq, type | VM_FRAME_FLAG_FINISH, - self, block->klass, /* th->passed_defined_class, */ + self, defined_class, VM_ENVVAL_PREV_EP_PTR(block->ep), iseq->iseq_encoded + opt_pc, cfp->sp + arg_size, iseq->local_size - arg_size, @@ -633,19 +638,21 @@ static inline VALUE vm_yield_with_cref(rb_thread_t *th, int argc, const VALUE *argv, const NODE *cref) { const rb_block_t *blockptr = check_block(th); - return invoke_block_from_c(th, blockptr, blockptr->self, argc, argv, 0, cref); + return invoke_block_from_c(th, blockptr, blockptr->self, argc, argv, 0, cref, + blockptr->klass); } static inline VALUE vm_yield(rb_thread_t *th, int argc, const VALUE *argv) { const rb_block_t *blockptr = check_block(th); - return invoke_block_from_c(th, blockptr, blockptr->self, argc, argv, 0, 0); + return invoke_block_from_c(th, blockptr, blockptr->self, argc, argv, 0, 0, + blockptr->klass); } -VALUE -rb_vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, VALUE self, - int argc, const VALUE *argv, const rb_block_t * blockptr) +static VALUE +vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, VALUE self, VALUE defined_class, + int argc, const VALUE *argv, const rb_block_t *blockptr) { VALUE val = Qundef; int state; @@ -656,7 +663,8 @@ rb_vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, VALUE self, if (!proc->is_from_method) { th->safe_level = proc->safe_level; } - val = invoke_block_from_c(th, &proc->block, self, argc, argv, blockptr, 0); + val = invoke_block_from_c(th, &proc->block, self, argc, argv, blockptr, 0, + defined_class); } TH_POP_TAG(); @@ -670,6 +678,14 @@ rb_vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, VALUE self, return val; } +VALUE +rb_vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, + int argc, const VALUE *argv, const rb_block_t *blockptr) +{ + return vm_invoke_proc(th, proc, proc->block.self, proc->block.klass, + argc, argv, blockptr); +} + /* special variable */ static rb_control_frame_t * @@ -731,7 +731,7 @@ VALUE rb_iseq_eval_main(VALUE iseqval); #endif int rb_thread_method_id_and_class(rb_thread_t *th, ID *idp, VALUE *klassp); -VALUE rb_vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, VALUE self, +VALUE rb_vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, int argc, const VALUE *argv, const rb_block_t *blockptr); VALUE rb_vm_make_proc(rb_thread_t *th, const rb_block_t *block, VALUE klass); VALUE rb_vm_make_env_object(rb_thread_t *th, rb_control_frame_t *cfp); @@ -126,7 +126,7 @@ vm_call0(rb_thread_t* th, VALUE recv, VALUE id, int argc, const VALUE *argv, case OPTIMIZED_METHOD_TYPE_CALL: { rb_proc_t *proc; GetProcPtr(recv, proc); - val = rb_vm_invoke_proc(th, proc, proc->block.self, argc, argv, blockptr); + val = rb_vm_invoke_proc(th, proc, argc, argv, blockptr); break; } default: diff --git a/vm_insnhelper.c b/vm_insnhelper.c index bb39b848cf..b774f1206f 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -466,7 +466,7 @@ vm_call_bmethod(rb_thread_t *th, VALUE recv, int argc, const VALUE *argv, /* control block frame */ th->passed_me = me; GetProcPtr(me->def->body.proc, proc); - val = rb_vm_invoke_proc(th, proc, recv, argc, argv, blockptr); + val = vm_invoke_proc(th, proc, recv, defined_class, argc, argv, blockptr); EXEC_EVENT_HOOK(th, RUBY_EVENT_RETURN, recv, me->called_id, me->klass); @@ -655,7 +655,7 @@ vm_call_method(rb_thread_t *th, rb_control_frame_t *cfp, MEMCPY(argv, cfp->sp - num, VALUE, num); cfp->sp -= num + 1; - val = rb_vm_invoke_proc(th, proc, proc->block.self, argc, argv, blockptr); + val = rb_vm_invoke_proc(th, proc, argc, argv, blockptr); break; } default: @@ -683,10 +683,6 @@ vm_call_method(rb_thread_t *th, rb_control_frame_t *cfp, val = vm_method_missing(th, id, recv, num, blockptr, stat); } else if (!(flag & VM_CALL_OPT_SEND_BIT) && (me->flag & NOEX_MASK) & NOEX_PROTECTED) { - if (RB_TYPE_P(defined_class, T_ICLASS)) { - defined_class = RBASIC(defined_class)->klass; - } - if (!rb_obj_is_kind_of(cfp->self, defined_class)) { val = vm_method_missing(th, id, recv, num, blockptr, NOEX_PROTECTED); } |