Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[flang][runtime] Catch error on Ew.0 output editing #78522

Merged
merged 1 commit into from
Jan 25, 2024

Conversation

klausler
Copy link
Contributor

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.

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 llvm#78390.
@llvmbot
Copy link
Collaborator

llvmbot commented Jan 17, 2024

@llvm/pr-subscribers-flang-runtime

Author: Peter Klausler (klausler)

Changes

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.


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 --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;"},

@klausler klausler merged commit 033b491 into llvm:main Jan 25, 2024
6 checks passed
@klausler klausler deleted the bug78390 branch January 25, 2024 22:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
flang:runtime flang Flang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Flang] WRITE with E20.0 of value 1.0 does not raise error condition as it should.
3 participants