[flang-commits] [flang] [flang][runtime] Allow already-documented missing 'w' on edit descriptor (PR #72901)
Peter Klausler via flang-commits
flang-commits at lists.llvm.org
Mon Nov 20 10:56:39 PST 2023
https://github.com/klausler created https://github.com/llvm/llvm-project/pull/72901
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 https://github.com/llvm/llvm-project/issues/72597.
>From 554ff3e2b057b4863a5b71b6d9f20503b6bfd8bb Mon Sep 17 00:00:00 2001
From: Peter Klausler <pklausler at nvidia.com>
Date: Mon, 20 Nov 2023 10:39:50 -0800
Subject: [PATCH] [flang][runtime] Allow already-documented missing 'w' on edit
descriptor
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 https://github.com/llvm/llvm-project/issues/72597.
---
flang/runtime/format-implementation.h | 73 ++++++++++++++-------------
flang/unittests/Runtime/Format.cpp | 3 +-
2 files changed, 39 insertions(+), 37 deletions(-)
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};
More information about the flang-commits
mailing list