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

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


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-flang-runtime

Author: Peter Klausler (klausler)

<details>
<summary>Changes</summary>

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.

---
Full diff: https://github.com/llvm/llvm-project/pull/71436.diff


3 Files Affected:

- (modified) flang/runtime/format-implementation.h (+3-2) 
- (modified) flang/runtime/format.h (+1) 
- (modified) flang/unittests/Runtime/Format.cpp (+4) 


``````````diff
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) {

``````````

</details>


https://github.com/llvm/llvm-project/pull/71436


More information about the flang-commits mailing list