[flang-commits] [flang] [flang][runtime] Correct automaticparenthesized format repetition case (PR #71436)

Peter Klausler via flang-commits flang-commits at lists.llvm.org
Mon Nov 6 11:46:03 PST 2023


https://github.com/klausler created https://github.com/llvm/llvm-project/pull/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.

>From 7cd7fa5f061ae625b6389108bca6d167c8fe3641 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 automaticparenthesized 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