summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author卜部昌平 <shyouhei@ruby-lang.org>2019-09-05 14:29:11 +0900
committer卜部昌平 <shyouhei@ruby-lang.org>2019-09-05 14:29:11 +0900
commit41bc766763dba63ae2529f2f9070b8e26399745c (patch)
treea2a149c5872d5df88828999853ed85f6475c1fa8
parentdd2b9d4a96e6c9784daf645efc79bef11eb1decb (diff)
interesting (but annoying) tidbit warning suppressed
This changeset is to suppress clang's -Wimplicit-int-float-conversion warning. In 64 bit signed long and IEEE 754 double combination (== almost everyone these days), LONG_MAX is 9,223,372,036,854,775,807. This value is _not_ exactly representable by double. The nearest value that a double can represnt is 9,223,372,036,854,775,808. It is one greater than LONG_MAX. Let's call this value the "x". The expression `LONG_MAX < yi` is a long versus double comparison. According to ISO/IEC 9899:1999 Section 6.3.1.8 (that defines the "usual rithmetic conversions"), The long value must first be casted into double. Because FLT_ROUNDS is typically 1 ("round to the nearest" mode), the conversion yields the "x" value shown above. So the comparison is in fact `x < yi`. This comparison is false for yi == x situation, i.e. yi is still bigger than LONG_MAX. On such situation the `yn = (long)yi;` statement that appear several lines below renders underfined behaviour, as per ISO/IEC 9899:1999 Section 6.3.1.3. To remedy, we just change the comparison from `<` to `<=` so that yi == x situation can properly be handled.
-rw-r--r--bignum.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/bignum.c b/bignum.c
index 6edb7f0dc3..5d14306d77 100644
--- a/bignum.c
+++ b/bignum.c
@@ -5369,6 +5369,15 @@ rb_integer_float_cmp(VALUE x, VALUE y)
return INT2FIX(-1);
}
+COMPILER_WARNING_PUSH
+#ifdef __has_warning
+#if __has_warning("-Wimplicit-int-float-conversion")
+COMPILER_WARNING_IGNORED(-Wimplicit-int-float-conversion)
+#endif
+#endif
+static const double LONG_MAX_as_double = LONG_MAX;
+COMPILER_WARNING_POP
+
VALUE
rb_integer_float_eq(VALUE x, VALUE y)
{
@@ -5388,7 +5397,7 @@ rb_integer_float_eq(VALUE x, VALUE y)
return Qtrue;
#else
long xn, yn;
- if (yi < LONG_MIN || LONG_MAX < yi)
+ if (yi < LONG_MIN || LONG_MAX_as_double <= yi)
return Qfalse;
xn = FIX2LONG(x);
yn = (long)yi;
@@ -5401,6 +5410,7 @@ rb_integer_float_eq(VALUE x, VALUE y)
return rb_big_eq(x, y);
}
+
VALUE
rb_big_cmp(VALUE x, VALUE y)
{