Skip to content

[flang][runtime] Allow already-documented missing 'w' on edit descriptor #72901

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

Merged
merged 1 commit into from
Nov 30, 2023

Conversation

klausler
Copy link
Contributor

As already documented in flang/docs/Extensions.md and implemented in the compilation-time format validator, we want to support at execution time the Intel (and presumably also Fujitsu) extension of allowing a missing width on an edit descriptor in a formatted I/O statement.

Fixes #72597.

As already documented in flang/docs/Extensions.md and implemented in the
compilation-time format validator, we want to support at execution time
the Intel (and presumably also Fujitsu) extension of allowing a missing
width on an edit descriptor in a formatted I/O statement.

Fixes llvm#72597.
@klausler klausler requested a review from vdonaldson November 20, 2023 18:56
@llvmbot llvmbot added flang:runtime flang Flang issues not falling into any other category labels Nov 20, 2023
@llvmbot
Copy link
Member

llvmbot commented Nov 20, 2023

@llvm/pr-subscribers-flang-runtime

Author: Peter Klausler (klausler)

Changes

As already documented in flang/docs/Extensions.md and implemented in the compilation-time format validator, we want to support at execution time the Intel (and presumably also Fujitsu) extension of allowing a missing width on an edit descriptor in a formatted I/O statement.

Fixes #72597.


Full diff: https://github.com/llvm/llvm-project/pull/72901.diff

2 Files Affected:

  • (modified) flang/runtime/format-implementation.h (+37-36)
  • (modified) flang/unittests/Runtime/Format.cpp (+2-1)
diff --git a/flang/runtime/format-implementation.h b/flang/runtime/format-implementation.h
index 57c176ea8d77cac..c54ac062c7beab9 100644
--- a/flang/runtime/format-implementation.h
+++ b/flang/runtime/format-implementation.h
@@ -416,14 +416,16 @@ std::optional<DataEdit> FormatControl<CONTEXT>::GetNextDataEdit(
   int repeat{CueUpNextDataEdit(context)};
   auto start{offset_};
   DataEdit edit;
+  edit.modes = context.mutableModes();
+  // Handle repeated nonparenthesized edit descriptors
+  edit.repeat = std::min(repeat, maxRepeat); // 0 if maxRepeat==0
+  if (repeat > maxRepeat) {
+    stack_[height_].start = start; // after repeat count
+    stack_[height_].remaining = repeat - edit.repeat;
+    ++height_;
+  }
   edit.descriptor = static_cast<char>(Capitalize(GetNextChar(context)));
-  if (edit.descriptor == 'E') {
-    if (auto next{static_cast<char>(Capitalize(PeekNext()))};
-        next == 'N' || next == 'S' || next == 'X') {
-      edit.variation = next;
-      ++offset_;
-    }
-  } else if (edit.descriptor == 'D' && Capitalize(PeekNext()) == 'T') {
+  if (edit.descriptor == 'D' && Capitalize(PeekNext()) == 'T') {
     // DT['iotype'][(v_list)] defined I/O
     edit.descriptor = DataEdit::DefinedDerivedType;
     ++offset_;
@@ -479,38 +481,37 @@ std::optional<DataEdit> FormatControl<CONTEXT>::GetNextDataEdit(
         return std::nullopt;
       }
     }
-  }
-  if (edit.descriptor == 'A' || edit.descriptor == 'L') {
-    // width is optional for A[w] or L[w]
-    auto ch{PeekNext()};
-    if (ch >= '0' && ch <= '9') {
-      edit.width = GetIntField(context);
-    }
-  } else if (edit.descriptor != DataEdit::DefinedDerivedType) {
-    edit.width = GetIntField(context);
-  }
-  if constexpr (std::is_base_of_v<InputStatementState, CONTEXT>) {
-    if (edit.width.value_or(-1) == 0) {
-      ReportBadFormat(context, "Input field width is zero", start);
+  } else { // not DT'iotype'
+    if (edit.descriptor == 'E') {
+      if (auto next{static_cast<char>(Capitalize(PeekNext()))};
+          next == 'N' || next == 'S' || next == 'X') {
+        edit.variation = next;
+        ++offset_;
+      }
     }
-  }
-  if (edit.descriptor != DataEdit::DefinedDerivedType && PeekNext() == '.') {
-    ++offset_;
-    edit.digits = GetIntField(context);
-    CharType ch{PeekNext()};
-    if (ch == 'e' || ch == 'E' || ch == 'd' || ch == 'D') {
-      ++offset_;
-      edit.expoDigits = GetIntField(context);
+    // Width is optional for A[w] in the standard and optional
+    // for Lw in most compilers.
+    // Intel & (presumably, from bug report) Fujitsu allow
+    // a missing 'w' & 'd'/'m' for other edit descriptors -- but not
+    // 'd'/'m' with a missing 'w' -- and so interpret "(E)" as "(E0)".
+    if (CharType ch{PeekNext()}; (ch >= '0' && ch <= '9') || ch == '.') {
+      edit.width = GetIntField(context);
+      if constexpr (std::is_base_of_v<InputStatementState, CONTEXT>) {
+        if (edit.width.value_or(-1) == 0) {
+          ReportBadFormat(context, "Input field width is zero", start);
+        }
+      }
+      if (PeekNext() == '.') {
+        ++offset_;
+        edit.digits = GetIntField(context);
+        if (CharType ch{PeekNext()};
+            ch == 'e' || ch == 'E' || ch == 'd' || ch == 'D') {
+          ++offset_;
+          edit.expoDigits = GetIntField(context);
+        }
+      }
     }
   }
-  edit.modes = context.mutableModes();
-  // Handle repeated nonparenthesized edit descriptors
-  edit.repeat = std::min(repeat, maxRepeat); // 0 if maxRepeat==0
-  if (repeat > maxRepeat) {
-    stack_[height_].start = start; // after repeat count
-    stack_[height_].remaining = repeat - edit.repeat;
-    ++height_;
-  }
   return edit;
 }
 
diff --git a/flang/unittests/Runtime/Format.cpp b/flang/unittests/Runtime/Format.cpp
index e9004b7798f3613..01803c628de26ad 100644
--- a/flang/unittests/Runtime/Format.cpp
+++ b/flang/unittests/Runtime/Format.cpp
@@ -111,6 +111,7 @@ TEST(FormatTests, FormatStringTraversal) {
           ResultsTy{"I4", "E10.1", "E10.1", "/", "I4", "E10.1", "E10.1", "/",
               "I4", "E10.1", "E10.1"},
           1},
+      {1, "(F)", ResultsTy{"F"}, 1}, // missing 'w'
   };
 
   for (const auto &[n, format, expect, repeat] : params) {
@@ -170,7 +171,7 @@ TEST(InvalidFormatFailure, MissingPrecision) {
       R"(Invalid FORMAT: integer expected at '\)')");
 }
 
-TEST(InvalidFormatFailure, MissingFormatWidth) {
+TEST(InvalidFormatFailure, MissingFormatWidthWithDigits) {
   static constexpr const char *format{"(F.9)"};
   static constexpr int repeat{1};
 

@klausler klausler merged commit c13f7e1 into llvm:main Nov 30, 2023
@klausler klausler deleted the bug72597 branch November 30, 2023 20:52
Guzhu-AMD pushed a commit to GPUOpen-Drivers/llvm-project that referenced this pull request Dec 7, 2023
Local branch amd-gfx abbd8f9 Merged main:a51196ec6ed7 into amd-gfx:1962fcd7d484
Remote branch main c13f7e1 [flang][runtime] Allow already-documented missing w on edit descriptor (llvm#72901)
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] Execution error of data edit descriptors without width
3 participants