diff options
author | 卜部昌平 <shyouhei@ruby-lang.org> | 2019-09-05 14:29:11 +0900 |
---|---|---|
committer | 卜部昌平 <shyouhei@ruby-lang.org> | 2019-09-05 14:29:11 +0900 |
commit | 41bc766763dba63ae2529f2f9070b8e26399745c (patch) | |
tree | a2a149c5872d5df88828999853ed85f6475c1fa8 | |
parent | dd2b9d4a96e6c9784daf645efc79bef11eb1decb (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.c | 12 |
1 files changed, 11 insertions, 1 deletions
@@ -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) { |