diff --git a/flang/include/flang/Evaluate/real.h b/flang/include/flang/Evaluate/real.h --- a/flang/include/flang/Evaluate/real.h +++ b/flang/include/flang/Evaluate/real.h @@ -221,21 +221,26 @@ return result; } ValueWithRealFlags intPart{ToWholeNumber(mode)}; - int exponent{intPart.value.Exponent()}; - result.flags.set( - RealFlag::Overflow, exponent >= exponentBias + result.value.bits); result.flags |= intPart.flags; - int shift{ - exponent - exponentBias - binaryPrecision + 1}; // positive -> left - result.value = - result.value.ConvertUnsigned(intPart.value.GetFraction().SHIFTR(-shift)) - .value.SHIFTL(shift); + int exponent{intPart.value.Exponent()}; + // shift positive -> left shift, negative -> right shift + int shift{exponent - exponentBias - binaryPrecision + 1}; + // Apply any right shift before moving to the result type + auto rshifted{intPart.value.GetFraction().SHIFTR(-shift)}; + auto converted{result.value.ConvertUnsigned(rshifted)}; + if (converted.overflow) { + result.flags.set(RealFlag::Overflow); + } + result.value = converted.value.SHIFTL(shift); + if (converted.value.CompareUnsigned(result.value.SHIFTR(shift)) != + Ordering::Equal) { + result.flags.set(RealFlag::Overflow); + } if (IsSignBitSet()) { - auto negated{result.value.Negate()}; - result.value = negated.value; - if (negated.overflow) { - result.flags.set(RealFlag::Overflow); - } + result.value = result.value.Negate().value; + } + if (IsSignBitSet() != result.value.IsNegative()) { + result.flags.set(RealFlag::Overflow); } if (result.flags.test(RealFlag::Overflow)) { result.value =