aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/ruby/ruby.h37
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)