aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog16
-rw-r--r--cont.c2
-rw-r--r--proc.c8
-rw-r--r--test/ruby/test_module.rb54
-rw-r--r--thread.c2
-rw-r--r--vm.c32
-rw-r--r--vm_core.h2
-rw-r--r--vm_eval.c2
-rw-r--r--vm_insnhelper.c8
9 files changed, 103 insertions, 23 deletions
diff --git a/ChangeLog b/ChangeLog
index d77dfc001f..ab16db8518 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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.
diff --git a/cont.c b/cont.c
index 1d90a2bfcb..548b163f7b 100644
--- a/cont.c
+++ b/cont.c
@@ -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();
diff --git a/proc.c b/proc.c
index 9ed6dbb2e7..753464bc32 100644
--- a/proc.c
+++ b/proc.c
@@ -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
diff --git a/thread.c b/thread.c
index 071f1ef5f7..831eb2a69e 100644
--- a/thread.c
+++ b/thread.c
@@ -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 {
diff --git a/vm.c b/vm.c
index 443260ea43..277e33d27a 100644
--- a/vm.c
+++ b/vm.c
@@ -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 *
diff --git a/vm_core.h b/vm_core.h
index 36fcf37a57..14cf38e756 100644
--- a/vm_core.h
+++ b/vm_core.h
@@ -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);
diff --git a/vm_eval.c b/vm_eval.c
index 04ae8fa422..ce5e340b3e 100644
--- a/vm_eval.c
+++ b/vm_eval.c
@@ -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);
}