Skip to content

Commit 9682b1f

Browse files
klauslerjeanPerier
authored andcommitted
[flang] Correct overflow detection in folding of real->integer conversions
INT, NINT, FLOOR, and CEILING were failing to report overflow as an error while folding operations with constant operands. Differential Revision: https://reviews.llvm.org/D109922
1 parent ad26cde commit 9682b1f

File tree

1 file changed

+18
-13
lines changed
  • flang/include/flang/Evaluate

1 file changed

+18
-13
lines changed

flang/include/flang/Evaluate/real.h

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -219,21 +219,26 @@ class Real : public common::RealDetails<PREC> {
219219
return result;
220220
}
221221
ValueWithRealFlags<Real> intPart{ToWholeNumber(mode)};
222-
int exponent{intPart.value.Exponent()};
223-
result.flags.set(
224-
RealFlag::Overflow, exponent >= exponentBias + result.value.bits);
225222
result.flags |= intPart.flags;
226-
int shift{
227-
exponent - exponentBias - binaryPrecision + 1}; // positive -> left
228-
result.value =
229-
result.value.ConvertUnsigned(intPart.value.GetFraction().SHIFTR(-shift))
230-
.value.SHIFTL(shift);
223+
int exponent{intPart.value.Exponent()};
224+
// shift positive -> left shift, negative -> right shift
225+
int shift{exponent - exponentBias - binaryPrecision + 1};
226+
// Apply any right shift before moving to the result type
227+
auto rshifted{intPart.value.GetFraction().SHIFTR(-shift)};
228+
auto converted{result.value.ConvertUnsigned(rshifted)};
229+
if (converted.overflow) {
230+
result.flags.set(RealFlag::Overflow);
231+
}
232+
result.value = converted.value.SHIFTL(shift);
233+
if (converted.value.CompareUnsigned(result.value.SHIFTR(shift)) !=
234+
Ordering::Equal) {
235+
result.flags.set(RealFlag::Overflow);
236+
}
231237
if (IsSignBitSet()) {
232-
auto negated{result.value.Negate()};
233-
result.value = negated.value;
234-
if (negated.overflow) {
235-
result.flags.set(RealFlag::Overflow);
236-
}
238+
result.value = result.value.Negate().value;
239+
}
240+
if (IsSignBitSet() != result.value.IsNegative()) {
241+
result.flags.set(RealFlag::Overflow);
237242
}
238243
if (result.flags.test(RealFlag::Overflow)) {
239244
result.value =

0 commit comments

Comments
 (0)