Skip to content

Commit 033b491

Browse files
authored
[flang][runtime] Catch error on Ew.0 output editing (#78522)
An Ew.0(Ee) or Ew.0(Ee) output edit descriptor with a scale factor of zero is an error condition, unless the output edit descriptor was originally Gw.0(Ee), list-directed, or just E0/D0 with no .d part. Fixes #78390.
1 parent 3bca850 commit 033b491

File tree

3 files changed

+14
-4
lines changed

3 files changed

+14
-4
lines changed

flang/runtime/edit-output.cpp

+12-2
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,11 @@ bool RealOutputEditing<KIND>::EditEorDOutput(const DataEdit &edit) {
334334
}
335335
++significantDigits;
336336
scale = std::min(scale, significantDigits + 1);
337+
} else if (edit.digits.value_or(1) == 0 && !edit.variation) {
338+
// F'2023 13.7.2.3.3 p5; does not apply to Gw.0(Ee) or E0(no d)
339+
io_.GetIoErrorHandler().SignalError(IostatErrorInFormat,
340+
"Output edit descriptor %cw.d must have d>0", edit.descriptor);
341+
return false;
337342
}
338343
// In EN editing, multiple attempts may be necessary, so this is a loop.
339344
while (true) {
@@ -549,6 +554,7 @@ bool RealOutputEditing<KIND>::EditFOutput(const DataEdit &edit) {
549554
template <int KIND>
550555
DataEdit RealOutputEditing<KIND>::EditForGOutput(DataEdit edit) {
551556
edit.descriptor = 'E';
557+
edit.variation = 'G'; // to suppress error for Ew.0
552558
int editWidth{edit.width.value_or(0)};
553559
int significantDigits{
554560
edit.digits.value_or(BinaryFloatingPoint::decimalPrecision)}; // 'd'
@@ -594,7 +600,9 @@ bool RealOutputEditing<KIND>::EditListDirectedOutput(const DataEdit &edit) {
594600
decimal::ConversionToDecimalResult converted{
595601
ConvertToDecimal(1, edit.modes.round)};
596602
if (IsInfOrNaN(converted.str, static_cast<int>(converted.length))) {
597-
return EditEorDOutput(edit);
603+
DataEdit copy{edit};
604+
copy.variation = DataEdit::ListDirected;
605+
return EditEorDOutput(copy);
598606
}
599607
int expo{converted.decimalExponent};
600608
// The decimal precision of 16-bit floating-point types is very low,
@@ -604,10 +612,12 @@ bool RealOutputEditing<KIND>::EditListDirectedOutput(const DataEdit &edit) {
604612
std::max(6, BinaryFloatingPoint::decimalPrecision)};
605613
if (expo < 0 || expo > maxExpo) {
606614
DataEdit copy{edit};
615+
copy.variation = DataEdit::ListDirected;
607616
copy.modes.scale = 1; // 1P
608617
return EditEorDOutput(copy);
618+
} else {
619+
return EditFOutput(edit);
609620
}
610-
return EditFOutput(edit);
611621
}
612622

613623
// 13.7.2.3.6 in F'2023

flang/runtime/format.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ struct DataEdit {
6363

6464
static constexpr char DefinedDerivedType{'d'}; // DT defined I/O
6565

66-
char variation{'\0'}; // N, S, or X for EN, ES, EX
66+
char variation{'\0'}; // N, S, or X for EN, ES, EX; G/l for original G/list
6767
std::optional<int> width; // the 'w' field; optional for A
6868
std::optional<int> digits; // the 'm' or 'd' field
6969
std::optional<int> expoDigits; // 'Ee' field

flang/unittests/Runtime/NumericalFormatTest.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,7 @@ TEST(IOApiTests, FormatDoubleValues) {
421421
{"(E62.55,';')",
422422
" 0.1000000000000000055511151231257827021181583404541015625E+"
423423
"00;"},
424-
{"(E0.0,';')", ".1E+00;"},
424+
{"(E0.1,';')", ".1E+00;"},
425425
{"(E0.55,';')",
426426
".1000000000000000055511151231257827021181583404541015625E+"
427427
"00;"},

0 commit comments

Comments
 (0)