diff options
-rw-r--r-- | ChangeLog | 7 | ||||
-rw-r--r-- | test/ruby/test_defined.rb | 15 | ||||
-rw-r--r-- | vm_insnhelper.c | 27 |
3 files changed, 42 insertions, 7 deletions
@@ -1,3 +1,10 @@ +Wed Jun 3 04:48:05 2015 Koichi Sasada <ko1@atdot.net> + + * vm_insnhelper.c (vm_defined): check respond_to_missing? + at defined?(func()). + + * test/ruby/test_defined.rb: add a test for this fix. + Wed Jun 3 04:34:39 2015 Koichi Sasada <ko1@atdot.net> * vm_insnhelper.c (vm_defined): skip respond_to_missing? when diff --git a/test/ruby/test_defined.rb b/test/ruby/test_defined.rb index 64757615ec..95a46ed984 100644 --- a/test/ruby/test_defined.rb +++ b/test/ruby/test_defined.rb @@ -223,6 +223,14 @@ class TestDefined < Test::Unit::TestCase def existing_method end + + def func_defined_existing_func + defined?(existing_method()) + end + + def func_defined_non_existing_func + defined?(non_existing_method()) + end end def test_method_by_respond_to_missing @@ -232,5 +240,12 @@ class TestDefined < Test::Unit::TestCase assert_equal(false, obj.called, bug_11211) assert_equal(nil, defined?(obj.non_existing_method), bug_11211) assert_equal(true, obj.called, bug_11211) + + bug_11212 = '[Bug #11212]' + obj = ExampleRespondToMissing.new + assert_equal("method", obj.func_defined_existing_func, bug_11212) + assert_equal(false, obj.called, bug_11212) + assert_equal(nil, obj.func_defined_non_existing_func, bug_11212) + assert_equal(true, obj.called, bug_11212) end end diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 619de32dce..eba27f42cc 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -2409,6 +2409,22 @@ FUNC_FASTCALL(rb_vm_opt_struct_aset)(rb_thread_t *th, rb_control_frame_t *reg_cf /* defined insn */ +static enum defined_type +check_resopnd_to_missing(VALUE obj, VALUE v) +{ + VALUE args[2]; + VALUE r; + + args[0] = obj; args[1] = Qfalse; + r = rb_check_funcall(v, idRespond_to_missing, 2, args); + if (r != Qundef && RTEST(r)) { + return DEFINED_METHOD; + } + else { + return 0; + } +} + static VALUE vm_defined(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_num_t op_type, VALUE obj, VALUE needstr, VALUE v) { @@ -2449,6 +2465,9 @@ vm_defined(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_num_t op_type, VALUE if (rb_method_boundp(klass, SYM2ID(obj), 0)) { expr_type = DEFINED_METHOD; } + else { + expr_type = check_resopnd_to_missing(obj, v); + } break; case DEFINED_METHOD:{ VALUE klass = CLASS_OF(v); @@ -2462,13 +2481,7 @@ vm_defined(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_num_t op_type, VALUE } } else { - VALUE args[2]; - VALUE r; - - args[0] = obj; args[1] = Qfalse; - r = rb_check_funcall(v, idRespond_to_missing, 2, args); - if (r != Qundef && RTEST(r)) - expr_type = DEFINED_METHOD; + expr_type = check_resopnd_to_missing(obj, v); } break; } |