diff --git a/flang/lib/Decimal/big-radix-floating-point.h b/flang/lib/Decimal/big-radix-floating-point.h --- a/flang/lib/Decimal/big-radix-floating-point.h +++ b/flang/lib/Decimal/big-radix-floating-point.h @@ -350,9 +350,9 @@ constexpr Raw Infinity() const { return (Raw{Real::maxExponent} << Real::significandBits) | SignBit(); } - static constexpr Raw NaN() { + constexpr Raw NaN(bool isQuiet = true) { return (Raw{Real::maxExponent} << Real::significandBits) | - (Raw{1} << (Real::significandBits - 2)); + (Raw{1} << (Real::significandBits - (isQuiet ? 1 : 2))) | SignBit(); } Digit digit_[maxDigits]; // in little-endian order: digit_[0] is LSD diff --git a/flang/lib/Decimal/decimal-to-binary.cpp b/flang/lib/Decimal/decimal-to-binary.cpp --- a/flang/lib/Decimal/decimal-to-binary.cpp +++ b/flang/lib/Decimal/decimal-to-binary.cpp @@ -407,36 +407,40 @@ return result; } else { // Could not parse a decimal floating-point number. p has been - // advanced over any leading spaces. - if ((!limit || limit >= p + 3) && toupper(p[0]) == 'N' && - toupper(p[1]) == 'A' && toupper(p[2]) == 'N') { + // advanced over any leading spaces. Most Fortran compilers set + // the sign bit for -NaN. + const char *q{p}; + if (!limit || q < limit) { + isNegative_ = *q == '-'; + if (isNegative_ || *q == '+') { + ++q; + } + } + if ((!limit || limit >= q + 3) && toupper(q[0]) == 'N' && + toupper(q[1]) == 'A' && toupper(q[2]) == 'N') { // NaN - p += 3; + p = q + 3; + bool isQuiet{true}; if ((!limit || p < limit) && *p == '(') { int depth{1}; do { ++p; if (limit && p >= limit) { // Invalid input - return {Real{NaN()}, Invalid}; + return {Real{NaN(false)}, Invalid}; } else if (*p == '(') { ++depth; } else if (*p == ')') { --depth; + } else if (*p != ' ') { + // Implementation dependent, but other compilers + // all return quiet NaNs. } } while (depth > 0); ++p; } - return {Real{NaN()}}; - } else { - // Try to parse Inf, maybe with a sign - const char *q{p}; - if (!limit || q < limit) { - isNegative_ = *q == '-'; - if (isNegative_ || *q == '+') { - ++q; - } - } + return {Real{NaN(isQuiet)}}; + } else { // Inf? if ((!limit || limit >= q + 3) && toupper(q[0]) == 'I' && toupper(q[1]) == 'N' && toupper(q[2]) == 'F') { if ((!limit || limit >= q + 8) && toupper(q[3]) == 'I' && diff --git a/flang/runtime/edit-output.cpp b/flang/runtime/edit-output.cpp --- a/flang/runtime/edit-output.cpp +++ b/flang/runtime/edit-output.cpp @@ -247,8 +247,8 @@ } } -template -decimal::ConversionToDecimalResult RealOutputEditing::Convert( +template +decimal::ConversionToDecimalResult RealOutputEditing::Convert( int significantDigits, enum decimal::FortranRounding rounding, int flags) { auto converted{decimal::ConvertToDecimal(buffer_, sizeof buffer_, static_cast(flags), @@ -262,8 +262,8 @@ } // 13.7.2.3.3 in F'2018 -template -bool RealOutputEditing::EditEorDOutput(const DataEdit &edit) { +template +bool RealOutputEditing::EditEorDOutput(const DataEdit &edit) { addSpaceBeforeCharacter(io_); int editDigits{edit.digits.value_or(0)}; // 'd' field int editWidth{edit.width.value_or(0)}; // 'w' field @@ -389,8 +389,8 @@ } // 13.7.2.3.2 in F'2018 -template -bool RealOutputEditing::EditFOutput(const DataEdit &edit) { +template +bool RealOutputEditing::EditFOutput(const DataEdit &edit) { addSpaceBeforeCharacter(io_); int fracDigits{edit.digits.value_or(0)}; // 'd' field const int editWidth{edit.width.value_or(0)}; // 'w' field @@ -496,8 +496,8 @@ } // 13.7.5.2.3 in F'2018 -template -DataEdit RealOutputEditing::EditForGOutput(DataEdit edit) { +template +DataEdit RealOutputEditing::EditForGOutput(DataEdit edit) { edit.descriptor = 'E'; int editWidth{edit.width.value_or(0)}; int significantDigits{ @@ -536,9 +536,8 @@ } // 13.10.4 in F'2018 -template -bool RealOutputEditing::EditListDirectedOutput( - const DataEdit &edit) { +template +bool RealOutputEditing::EditListDirectedOutput(const DataEdit &edit) { decimal::ConversionToDecimalResult converted{Convert(1, edit.modes.round)}; if (IsInfOrNaN(converted)) { return EditEorDOutput(edit); @@ -558,8 +557,8 @@ } // 13.7.5.2.6 in F'2018 -template -bool RealOutputEditing::EditEXOutput(const DataEdit &) { +template +bool RealOutputEditing::EditEXOutput(const DataEdit &) { io_.GetIoErrorHandler().Crash( "not yet implemented: EX output editing"); // TODO }