diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/ruby/ruby.h | 37 |
1 files changed, 31 insertions, 6 deletions
diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h index d770c30735..0cd88fb002 100644 --- a/include/ruby/ruby.h +++ b/include/ruby/ruby.h @@ -1504,6 +1504,29 @@ rb_integer_type_p(VALUE obj) } #endif +static inline int +rb_long2fix_overflow(long l, VALUE *ptr) +{ +#ifdef HAVE_BUILTIN___BUILTIN_MUL_OVERFLOW + SIGNED_VALUE v; + if (__builtin_mul_overflow(l, 2, &v)) { + return 1; + } + else { + *ptr = ((VALUE)v) | RUBY_FIXNUM_FLAG; + return 0; + } +#else + if (RB_FIXABLE(l)) { + *ptr = RB_LONG2FIX(l); + return 0; + } + else { + return 1; + } +#endif +} + #if SIZEOF_INT < SIZEOF_LONG # define RB_INT2NUM(v) RB_INT2FIX((int)(v)) # define RB_UINT2NUM(v) RB_LONG2FIX((unsigned int)(v)) @@ -1511,10 +1534,11 @@ rb_integer_type_p(VALUE obj) static inline VALUE rb_int2num_inline(int v) { - if (RB_FIXABLE(v)) - return RB_INT2FIX(v); - else + VALUE ret; + if (rb_long2fix_overflow(v, &ret)) return rb_int2big(v); + else + return ret; } #define RB_INT2NUM(x) rb_int2num_inline(x) @@ -1534,10 +1558,11 @@ rb_uint2num_inline(unsigned int v) static inline VALUE rb_long2num_inline(long v) { - if (RB_FIXABLE(v)) - return RB_LONG2FIX(v); - else + VALUE ret; + if (rb_long2fix_overflow(v, &ret)) return rb_int2big(v); + else + return ret; } #define RB_LONG2NUM(x) rb_long2num_inline(x) |