diff --git a/flang/runtime/edit-output.cpp b/flang/runtime/edit-output.cpp index 26e066c85fed3..b474c8cd91bae 100644 --- a/flang/runtime/edit-output.cpp +++ b/flang/runtime/edit-output.cpp @@ -334,6 +334,11 @@ bool RealOutputEditing::EditEorDOutput(const DataEdit &edit) { } ++significantDigits; scale = std::min(scale, significantDigits + 1); + } else if (edit.digits.value_or(1) == 0 && !edit.variation) { + // F'2023 13.7.2.3.3 p5; does not apply to Gw.0(Ee) or E0(no d) + io_.GetIoErrorHandler().SignalError(IostatErrorInFormat, + "Output edit descriptor %cw.d must have d>0", edit.descriptor); + return false; } // In EN editing, multiple attempts may be necessary, so this is a loop. while (true) { @@ -549,6 +554,7 @@ bool RealOutputEditing::EditFOutput(const DataEdit &edit) { template DataEdit RealOutputEditing::EditForGOutput(DataEdit edit) { edit.descriptor = 'E'; + edit.variation = 'G'; // to suppress error for Ew.0 int editWidth{edit.width.value_or(0)}; int significantDigits{ edit.digits.value_or(BinaryFloatingPoint::decimalPrecision)}; // 'd' @@ -594,7 +600,9 @@ bool RealOutputEditing::EditListDirectedOutput(const DataEdit &edit) { decimal::ConversionToDecimalResult converted{ ConvertToDecimal(1, edit.modes.round)}; if (IsInfOrNaN(converted.str, static_cast(converted.length))) { - return EditEorDOutput(edit); + DataEdit copy{edit}; + copy.variation = DataEdit::ListDirected; + return EditEorDOutput(copy); } int expo{converted.decimalExponent}; // The decimal precision of 16-bit floating-point types is very low, @@ -604,10 +612,12 @@ bool RealOutputEditing::EditListDirectedOutput(const DataEdit &edit) { std::max(6, BinaryFloatingPoint::decimalPrecision)}; if (expo < 0 || expo > maxExpo) { DataEdit copy{edit}; + copy.variation = DataEdit::ListDirected; copy.modes.scale = 1; // 1P return EditEorDOutput(copy); + } else { + return EditFOutput(edit); } - return EditFOutput(edit); } // 13.7.2.3.6 in F'2023 diff --git a/flang/runtime/format.h b/flang/runtime/format.h index 989006ecd85ca..1fe0802ac43c6 100644 --- a/flang/runtime/format.h +++ b/flang/runtime/format.h @@ -63,7 +63,7 @@ struct DataEdit { static constexpr char DefinedDerivedType{'d'}; // DT defined I/O - char variation{'\0'}; // N, S, or X for EN, ES, EX + char variation{'\0'}; // N, S, or X for EN, ES, EX; G/l for original G/list std::optional width; // the 'w' field; optional for A std::optional digits; // the 'm' or 'd' field std::optional expoDigits; // 'Ee' field diff --git a/flang/unittests/Runtime/NumericalFormatTest.cpp b/flang/unittests/Runtime/NumericalFormatTest.cpp index 9dd2771fe4a75..03a2be3ca56df 100644 --- a/flang/unittests/Runtime/NumericalFormatTest.cpp +++ b/flang/unittests/Runtime/NumericalFormatTest.cpp @@ -421,7 +421,7 @@ TEST(IOApiTests, FormatDoubleValues) { {"(E62.55,';')", " 0.1000000000000000055511151231257827021181583404541015625E+" "00;"}, - {"(E0.0,';')", ".1E+00;"}, + {"(E0.1,';')", ".1E+00;"}, {"(E0.55,';')", ".1000000000000000055511151231257827021181583404541015625E+" "00;"},