-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[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
Conversation
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.
@llvm/pr-subscribers-flang-runtime Author: Peter Klausler (klausler) ChangesAs 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:
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};
|
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)
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.