[flang-commits] [flang] [flang][runtime] Catch error on Ew.0 output editing (PR #78522)
via flang-commits
flang-commits at lists.llvm.org
Wed Jan 17 15:39:49 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-runtime
Author: Peter Klausler (klausler)
<details>
<summary>Changes</summary>
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 https://github.com/llvm/llvm-project/issues/78390.
---
Full diff: https://github.com/llvm/llvm-project/pull/78522.diff
3 Files Affected:
- (modified) flang/runtime/edit-output.cpp (+12-2)
- (modified) flang/runtime/format.h (+1-1)
- (modified) flang/unittests/Runtime/NumericalFormatTest.cpp (+1-1)
``````````diff
diff --git a/flang/runtime/edit-output.cpp b/flang/runtime/edit-output.cpp
index 26e066c85fed39..b474c8cd91bae4 100644
--- a/flang/runtime/edit-output.cpp
+++ b/flang/runtime/edit-output.cpp
@@ -334,6 +334,11 @@ bool RealOutputEditing<KIND>::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<KIND>::EditFOutput(const DataEdit &edit) {
template <int KIND>
DataEdit RealOutputEditing<KIND>::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<KIND>::EditListDirectedOutput(const DataEdit &edit) {
decimal::ConversionToDecimalResult converted{
ConvertToDecimal(1, edit.modes.round)};
if (IsInfOrNaN(converted.str, static_cast<int>(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<KIND>::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 989006ecd85cab..1fe0802ac43c69 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<int> width; // the 'w' field; optional for A
std::optional<int> digits; // the 'm' or 'd' field
std::optional<int> expoDigits; // 'Ee' field
diff --git a/flang/unittests/Runtime/NumericalFormatTest.cpp b/flang/unittests/Runtime/NumericalFormatTest.cpp
index 9dd2771fe4a753..03a2be3ca56df7 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;"},
``````````
</details>
https://github.com/llvm/llvm-project/pull/78522
More information about the flang-commits
mailing list