[flang-commits] [flang] c13f7e1 - [flang][runtime] Allow already-documented missing 'w' on edit descriptor (#72901)
via flang-commits
flang-commits at lists.llvm.org
Thu Nov 30 12:52:02 PST 2023
Author: Peter Klausler
Date: 2023-11-30T12:51:56-08:00
New Revision: c13f7e17409b6fed29696c2bbe59efc3af3a408b
URL: https://github.com/llvm/llvm-project/commit/c13f7e17409b6fed29696c2bbe59efc3af3a408b
DIFF: https://github.com/llvm/llvm-project/commit/c13f7e17409b6fed29696c2bbe59efc3af3a408b.diff
LOG: [flang][runtime] Allow already-documented missing 'w' on edit descriptor (#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.
Added:
Modified:
flang/runtime/format-implementation.h
flang/unittests/Runtime/Format.cpp
Removed:
################################################################################
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