diff --git a/flang/lib/Evaluate/real.cpp b/flang/lib/Evaluate/real.cpp --- a/flang/lib/Evaluate/real.cpp +++ b/flang/lib/Evaluate/real.cpp @@ -745,12 +745,12 @@ return *this; } else if (IsInfinite()) { return NotANumber(); - } else if (IsZero()) { - return TINY(); + } else if (IsZero() || IsSubnormal()) { + return TINY(); // mandated by standard } else { Real result; result.Normalize(false, Exponent(), Fraction::MASKR(1)); - return result; + return result.IsZero() ? TINY() : result; } } diff --git a/flang/runtime/numeric.cpp b/flang/runtime/numeric.cpp --- a/flang/runtime/numeric.cpp +++ b/flang/runtime/numeric.cpp @@ -239,8 +239,9 @@ // subnormal. return std::numeric_limits::min(); // 0 -> TINY(x) } else { - return std::ldexp( - static_cast(1.0), std::ilogb(x) + 1 - PREC); // 2**(e-p) + T result{ + std::ldexp(static_cast(1.0), std::ilogb(x) + 1 - PREC)}; // 2**(e-p) + return result == 0 ? /*TINY(x)*/ std::numeric_limits::min() : result; } } diff --git a/flang/test/Evaluate/fold-spacing.f90 b/flang/test/Evaluate/fold-spacing.f90 --- a/flang/test/Evaluate/fold-spacing.f90 +++ b/flang/test/Evaluate/fold-spacing.f90 @@ -7,6 +7,7 @@ logical, parameter :: test_4 = spacing(0.) == tiny(0.) logical, parameter :: test_5 = spacing(tiny(0.)) == 1.e-45 logical, parameter :: test_6 = spacing(8388608.) == 1. + logical, parameter :: test_7 = spacing(spacing(tiny(.0))) == tiny(0.) logical, parameter :: test_11 = rrspacing(3.0) == scale(0.75, 24) logical, parameter :: test_12 = rrspacing(-3.0) == scale(0.75, 24) logical, parameter :: test_13 = rrspacing(3.0d0) == scale(0.75, 53)