[flang-commits] [flang] [flang][runtime] Correct automatic parenthesized format repetition case (PR #71436)
Peter Klausler via flang-commits
flang-commits at lists.llvm.org
Mon Nov 6 11:46:41 PST 2023
https://github.com/klausler updated https://github.com/llvm/llvm-project/pull/71436
>From 1b88d71259a8168196bdb9fb058a5a6506c03faa Mon Sep 17 00:00:00 2001
From: Peter Klausler <pklausler at nvidia.com>
Date: Mon, 6 Nov 2023 11:36:44 -0800
Subject: [PATCH] [flang][runtime] Correct automatic parenthesized format
repetition case
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.
---
flang/runtime/format-implementation.h | 5 +++--
flang/runtime/format.h | 1 +
flang/unittests/Runtime/Format.cpp | 4 ++++
3 files changed, 8 insertions(+), 2 deletions(-)
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) {
More information about the flang-commits
mailing list