From 13149a59d8472db4cdd5a63a3eb2e7296e9a6713 Mon Sep 17 00:00:00 2001 From: nobu Date: Tue, 1 Nov 2016 22:34:30 +0000 Subject: numeric.c: bit op with non-integer * numeric.c (rb_num_coerce_bit): enable bit operations with coercing by non-integer object. [ruby-core:77783] [Bug #12875] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@56543 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- numeric.c | 55 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 20 deletions(-) (limited to 'numeric.c') diff --git a/numeric.c b/numeric.c index 75e0ebf468..d317d046c6 100644 --- a/numeric.c +++ b/numeric.c @@ -293,21 +293,27 @@ num_funcall0(VALUE x, ID func) return rb_exec_recursive(num_funcall_op_0, x, (VALUE)func); } +static void +num_funcall_op_1_recursion(VALUE x, ID func, VALUE y) +{ + const char *name = rb_id2name(func); + if (ISALNUM(name[0])) { + rb_name_error(func, "%"PRIsVALUE".%"PRIsVALUE"(%"PRIsVALUE")", + x, ID2SYM(func), y); + } + else { + rb_name_error(func, "%"PRIsVALUE"%"PRIsVALUE"%"PRIsVALUE, + x, ID2SYM(func), y); + } +} + static VALUE num_funcall_op_1(VALUE y, VALUE arg, int recursive) { ID func = (ID)((VALUE *)arg)[0]; VALUE x = ((VALUE *)arg)[1]; if (recursive) { - const char *name = rb_id2name(func); - if (ISALNUM(name[0])) { - rb_name_error(func, "%"PRIsVALUE".%"PRIsVALUE"(%"PRIsVALUE")", - x, ID2SYM(func), y); - } - else { - rb_name_error(func, "%"PRIsVALUE"%"PRIsVALUE"%"PRIsVALUE, - x, ID2SYM(func), y); - } + num_funcall_op_1_recursion(x, func, y); } return rb_funcall(x, func, 1, y); } @@ -4128,24 +4134,33 @@ int_comp(VALUE num) return Qnil; } -static int -bit_coerce(VALUE *x, VALUE *y) +static VALUE +num_funcall_bit_1(VALUE y, VALUE arg, int recursive) { - if (!RB_INTEGER_TYPE_P(*y)) { - VALUE orig = *x; - do_coerce(x, y, TRUE); - if (!RB_INTEGER_TYPE_P(*x) && !RB_INTEGER_TYPE_P(*y)) { - coerce_failed(orig, *y); - } + ID func = (ID)((VALUE *)arg)[0]; + VALUE x = ((VALUE *)arg)[1]; + if (recursive) { + num_funcall_op_1_recursion(x, func, y); } - return TRUE; + return rb_check_funcall(x, func, 1, &y); } VALUE rb_num_coerce_bit(VALUE x, VALUE y, ID func) { - bit_coerce(&x, &y); - return num_funcall1(x, func, y); + VALUE ret, args[3]; + + args[0] = (VALUE)func; + args[1] = x; + args[2] = y; + do_coerce(&args[1], &args[2], TRUE); + ret = rb_exec_recursive_paired(num_funcall_bit_1, + args[2], args[1], (VALUE)args); + if (ret == Qundef) { + /* show the original object, not coerced object */ + coerce_failed(x, y); + } + return ret; } /* -- cgit v1.2.3