[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