-
Notifications
You must be signed in to change notification settings - Fork 10.8k
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] Correct automatic parenthesized format repetition case #71436
Conversation
In Fortran, a format automatically repeats, with a line break, until all the data items of a data transfer statement have been consumed. PRINT "(3I4)", 1, 2, 3, 4, 5, 6 prints two lines, for example, three values each. When there are nested parentheses in a format, the rightmost set of parentheses at the top level are used for automatic repetition. PRINT "(I4,2(I4))" 1, 2, 3, 4, 5, 6, 7 print three lines, with three values on the first and two each on the later ones. Fix a bug in format interpretation that causes the detection of the "rightmost" set of parentheses to take place on each pass, leading to problems when parentheses are even further nested.
@llvm/pr-subscribers-flang-runtime Author: Peter Klausler (klausler) ChangesIn Fortran, a format automatically repeats, with a line break, until all the data items of a data transfer statement have been consumed. PRINT "(3I4)", 1, 2, 3, 4, 5, 6 prints two lines, for example, three values each. When there are nested parentheses in a format, the rightmost set of parentheses at the top level are used for automatic repetition. PRINT "(I4,2(I4))" 1, 2, 3, 4, 5, 6, 7 print three lines, with three values on the first and two each on the later ones. Fix a bug in format interpretation that causes the detection of the "rightmost" set of parentheses to take place on each pass, leading to problems when parentheses are even further nested. Full diff: https://github.com/llvm/llvm-project/pull/71436.diff 3 Files Affected:
diff --git a/flang/runtime/format-implementation.h b/flang/runtime/format-implementation.h
index 0daacc6bcccbb5f..57c176ea8d77cac 100644
--- a/flang/runtime/format-implementation.h
+++ b/flang/runtime/format-implementation.h
@@ -284,8 +284,8 @@ int FormatControl<CONTEXT>::CueUpNextDataEdit(Context &context, bool stop) {
} else {
stack_[height_].remaining = 0;
}
- if (height_ == 1) {
- // Subtle point (F'2018 13.4 para 9): tha last parenthesized group
+ if (height_ == 1 && !hitEnd_) {
+ // Subtle point (F'2018 13.4 para 9): the last parenthesized group
// at height 1 becomes the restart point after control reaches the
// end of the format, including its repeat count.
stack_[0].start = maybeReversionPoint;
@@ -300,6 +300,7 @@ int FormatControl<CONTEXT>::CueUpNextDataEdit(Context &context, bool stop) {
return 0; // end of FORMAT and no data items remain
}
context.AdvanceRecord(); // implied / before rightmost )
+ hitEnd_ = true;
}
auto restart{stack_[height_ - 1].start};
if (format_[restart] == '(') {
diff --git a/flang/runtime/format.h b/flang/runtime/format.h
index b9f8f73a48dec7a..989006ecd85cab0 100644
--- a/flang/runtime/format.h
+++ b/flang/runtime/format.h
@@ -184,6 +184,7 @@ template <typename CONTEXT> class FormatControl {
const std::uint8_t maxHeight_{maxMaxHeight};
std::uint8_t height_{0};
bool freeFormat_{false};
+ bool hitEnd_{false};
const CharType *format_{nullptr};
int formatLength_{0}; // in units of characters
int offset_{0}; // next item is at format_[offset_]
diff --git a/flang/unittests/Runtime/Format.cpp b/flang/unittests/Runtime/Format.cpp
index 1f55b39d5905331..e9004b7798f3613 100644
--- a/flang/unittests/Runtime/Format.cpp
+++ b/flang/unittests/Runtime/Format.cpp
@@ -107,6 +107,10 @@ TEST(FormatTests, FormatStringTraversal) {
ResultsTy{"'PI='", "F9.7", "'PI='", "F9.7"}, 1},
{2, "(*('PI=',F9.7,:))", ResultsTy{"'PI='", "F9.7", "'PI='", "F9.7"}, 1},
{1, "(3F9.7)", ResultsTy{"2*F9.7"}, 2},
+ {9, "((I4,2(E10.1)))",
+ ResultsTy{"I4", "E10.1", "E10.1", "/", "I4", "E10.1", "E10.1", "/",
+ "I4", "E10.1", "E10.1"},
+ 1},
};
for (const auto &[n, format, expect, repeat] : params) {
|
…se (llvm#71436) In Fortran, a format automatically repeats, with a line break, until all the data items of a data transfer statement have been consumed. PRINT "(3I4)", 1, 2, 3, 4, 5, 6 prints two lines, for example, three values each. When there are nested parentheses in a format, the rightmost set of parentheses at the top level are used for automatic repetition. PRINT "(I4,2(I4))" 1, 2, 3, 4, 5, 6, 7 print three lines, with three values on the first and two each on the later ones. Fix a bug in format interpretation that causes the detection of the "rightmost" set of parentheses to take place on each pass, leading to problems when parentheses are even further nested.
In Fortran, a format automatically repeats, with a line break, until all the data items of a data transfer statement have been consumed. PRINT "(3I4)", 1, 2, 3, 4, 5, 6 prints two lines, for example, three values each.
When there are nested parentheses in a format, the rightmost set of parentheses at the top level are used for automatic repetition. PRINT "(I4,2(I4))" 1, 2, 3, 4, 5, 6, 7 print three lines, with three values on the first and two each on the later ones.
Fix a bug in format interpretation that causes the detection of the "rightmost" set of parentheses to take place on each pass, leading to problems when parentheses are even further nested.