[flang-commits] [flang] e782360 - [flang] Complete the fix for NAMELIST look-ahead case

Peter Klausler via flang-commits flang-commits at lists.llvm.org
Mon Nov 8 10:01:30 PST 2021


Author: Peter Klausler
Date: 2021-11-08T10:01:16-08:00
New Revision: e7823608bc8e63f409ecd262b0e4a5a65a2ca9f8

URL: https://github.com/llvm/llvm-project/commit/e7823608bc8e63f409ecd262b0e4a5a65a2ca9f8
DIFF: https://github.com/llvm/llvm-project/commit/e7823608bc8e63f409ecd262b0e4a5a65a2ca9f8.diff

LOG: [flang] Complete the fix for NAMELIST look-ahead case

When processing the devious NAMELIST input

  &group logarray = t t t
    = 666 /

for LOGICAL::logarray(3) and INTEGER::t, the runtime library
needs to do some look-ahead on the input stream to make sure
that the last "t" on the first line is a truth value rather than
an item name -- which in this case it is.  This look-ahead
was implemented in a previous patch but only worked for internal
input cases; this patch implements look-ahead capabilities for
input from an external file, too (and also adjusts repeated
list-directed input items to use this infrastructure, too).

Differential Revision: https://reviews.llvm.org/D113311

Added: 
    

Modified: 
    flang/runtime/connection.cpp
    flang/runtime/connection.h
    flang/runtime/io-stmt.cpp
    flang/runtime/io-stmt.h
    flang/runtime/namelist.cpp
    flang/runtime/unit.cpp

Removed: 
    


################################################################################
diff  --git a/flang/runtime/connection.cpp b/flang/runtime/connection.cpp
index 29d3220f43fc..765ce90520c2 100644
--- a/flang/runtime/connection.cpp
+++ b/flang/runtime/connection.cpp
@@ -8,6 +8,7 @@
 
 #include "connection.h"
 #include "environment.h"
+#include "io-stmt.h"
 #include <algorithm>
 
 namespace Fortran::runtime::io {
@@ -33,4 +34,21 @@ void ConnectionState::HandleAbsolutePosition(std::int64_t n) {
 void ConnectionState::HandleRelativePosition(std::int64_t n) {
   positionInRecord = std::max(leftTabLimit.value_or(0), positionInRecord + n);
 }
+
+SavedPosition::SavedPosition(IoStatementState &io) : io_{io} {
+  ConnectionState &conn{io_.GetConnectionState()};
+  saved_ = conn;
+  conn.pinnedFrame = true;
+}
+
+SavedPosition::~SavedPosition() {
+  ConnectionState &conn{io_.GetConnectionState()};
+  while (conn.currentRecordNumber > saved_.currentRecordNumber) {
+    io_.BackspaceRecord();
+  }
+  conn.leftTabLimit = saved_.leftTabLimit;
+  conn.furthestPositionInRecord = saved_.furthestPositionInRecord;
+  conn.positionInRecord = saved_.positionInRecord;
+  conn.pinnedFrame = saved_.pinnedFrame;
+}
 } // namespace Fortran::runtime::io

diff  --git a/flang/runtime/connection.h b/flang/runtime/connection.h
index dfeebeb522dc..0eb2038500b2 100644
--- a/flang/runtime/connection.h
+++ b/flang/runtime/connection.h
@@ -17,6 +17,8 @@
 
 namespace Fortran::runtime::io {
 
+class IoStatementState;
+
 enum class Direction { Output, Input };
 enum class Access { Sequential, Direct, Stream };
 
@@ -57,40 +59,25 @@ struct ConnectionState : public ConnectionAttributes {
   // or an end-of-file READ condition on a sequential access file
   std::optional<std::int64_t> endfileRecordNumber;
 
+  // Mutable modes set at OPEN() that can be overridden in READ/WRITE & FORMAT
+  MutableModes modes; // BLANK=, DECIMAL=, SIGN=, ROUND=, PAD=, DELIM=, kP
+
   // Set when processing repeated items during list-directed & NAMELIST input
   // in order to keep a span of records in frame on a non-positionable file,
   // so that backspacing to the beginning of the repeated item doesn't require
   // repositioning the external storage medium when that's impossible.
-  std::optional<std::int64_t> resumptionRecordNumber;
-
-  // Mutable modes set at OPEN() that can be overridden in READ/WRITE & FORMAT
-  MutableModes modes; // BLANK=, DECIMAL=, SIGN=, ROUND=, PAD=, DELIM=, kP
+  bool pinnedFrame{false};
 };
 
 // Utility class for capturing and restoring a position in an input stream.
 class SavedPosition {
 public:
-  explicit SavedPosition(ConnectionState &c)
-      : connection_{c}, positionInRecord_{c.positionInRecord},
-        furthestPositionInRecord_{c.furthestPositionInRecord},
-        leftTabLimit_{c.leftTabLimit}, previousResumptionRecordNumber_{
-                                           c.resumptionRecordNumber} {
-    c.resumptionRecordNumber = c.currentRecordNumber;
-  }
-  ~SavedPosition() {
-    connection_.currentRecordNumber = *connection_.resumptionRecordNumber;
-    connection_.resumptionRecordNumber = previousResumptionRecordNumber_;
-    connection_.leftTabLimit = leftTabLimit_;
-    connection_.furthestPositionInRecord = furthestPositionInRecord_;
-    connection_.positionInRecord = positionInRecord_;
-  }
+  explicit SavedPosition(IoStatementState &);
+  ~SavedPosition();
 
 private:
-  ConnectionState &connection_;
-  std::int64_t positionInRecord_;
-  std::int64_t furthestPositionInRecord_;
-  std::optional<std::int64_t> leftTabLimit_;
-  std::optional<std::int64_t> previousResumptionRecordNumber_;
+  IoStatementState &io_;
+  ConnectionState saved_;
 };
 
 } // namespace Fortran::runtime::io

diff  --git a/flang/runtime/io-stmt.cpp b/flang/runtime/io-stmt.cpp
index 44fc7aefea6e..784d14496aac 100644
--- a/flang/runtime/io-stmt.cpp
+++ b/flang/runtime/io-stmt.cpp
@@ -680,14 +680,8 @@ ListDirectedStatementState<Direction::Input>::GetNextDataEdit(
     comma = ';';
   }
   if (remaining_ > 0 && !realPart_) { // "r*c" repetition in progress
-    RUNTIME_CHECK(
-        io.GetIoErrorHandler(), connection.resumptionRecordNumber.has_value());
-    while (connection.currentRecordNumber >
-        connection.resumptionRecordNumber.value_or(
-            connection.currentRecordNumber)) {
-      io.BackspaceRecord();
-    }
-    connection.HandleAbsolutePosition(repeatPositionInRecord_);
+    RUNTIME_CHECK(io.GetIoErrorHandler(), repeatPosition_.has_value());
+    repeatPosition_.reset(); // restores the saved position
     if (!imaginaryPart_) {
       edit.repeat = std::min<int>(remaining_, maxRepeat);
       auto ch{io.GetCurrentChar()};
@@ -697,8 +691,8 @@ ListDirectedStatementState<Direction::Input>::GetNextDataEdit(
       }
     }
     remaining_ -= edit.repeat;
-    if (remaining_ <= 0) {
-      connection.resumptionRecordNumber.reset();
+    if (remaining_ > 0) {
+      repeatPosition_.emplace(io);
     }
     return edit;
   }
@@ -761,11 +755,8 @@ ListDirectedStatementState<Direction::Input>::GetNextDataEdit(
       edit.repeat = std::min<int>(r, maxRepeat);
       remaining_ = r - edit.repeat;
       if (remaining_ > 0) {
-        connection.resumptionRecordNumber = connection.currentRecordNumber;
-      } else {
-        connection.resumptionRecordNumber.reset();
+        repeatPosition_.emplace(io);
       }
-      repeatPositionInRecord_ = connection.positionInRecord;
     } else { // not a repetition count, just an integer value; rewind
       connection.positionInRecord = start;
     }

diff  --git a/flang/runtime/io-stmt.h b/flang/runtime/io-stmt.h
index 7e683b146eb1..0006cab2b2ae 100644
--- a/flang/runtime/io-stmt.h
+++ b/flang/runtime/io-stmt.h
@@ -241,7 +241,7 @@ class ListDirectedStatementState<Direction::Input>
 
 private:
   int remaining_{0}; // for "r*" repetition
-  std::int64_t repeatPositionInRecord_;
+  std::optional<SavedPosition> repeatPosition_;
   bool eatComma_{false}; // consume comma after previously read item
   bool hitSlash_{false}; // once '/' is seen, nullify further items
   bool realPart_{false};

diff  --git a/flang/runtime/namelist.cpp b/flang/runtime/namelist.cpp
index 03fddd61f24d..11fe49b5fc9a 100644
--- a/flang/runtime/namelist.cpp
+++ b/flang/runtime/namelist.cpp
@@ -359,7 +359,7 @@ bool IsNamelistName(IoStatementState &io) {
   if (io.get_if<ListDirectedStatementState<Direction::Input>>()) {
     ConnectionState &connection{io.GetConnectionState()};
     if (connection.modes.inNamelist) {
-      SavedPosition savedPosition{connection};
+      SavedPosition savedPosition{io};
       if (auto ch{io.GetNextNonBlank()}) {
         if (IsLegalIdStart(*ch)) {
           do {
@@ -368,7 +368,7 @@ bool IsNamelistName(IoStatementState &io) {
           } while (ch && IsLegalIdChar(*ch));
           ch = io.GetNextNonBlank();
           // TODO: how to deal with NaN(...) ambiguity?
-          return ch && (ch == '=' || ch == '(' || ch == '%');
+          return ch && (*ch == '=' || *ch == '(' || *ch == '%');
         }
       }
     }

diff  --git a/flang/runtime/unit.cpp b/flang/runtime/unit.cpp
index 575af15513d7..829b471f3424 100644
--- a/flang/runtime/unit.cpp
+++ b/flang/runtime/unit.cpp
@@ -406,30 +406,30 @@ void ExternalFileUnit::FinishReadingRecord(IoErrorHandler &handler) {
     // avoid bogus crashes in END/ERR circumstances
   } else if (access == Access::Sequential) {
     RUNTIME_CHECK(handler, recordLength.has_value());
+    recordOffsetInFrame_ += *recordLength;
     if (isFixedRecordLength && access == Access::Direct) {
-      frameOffsetInFile_ += recordOffsetInFrame_ + *recordLength;
+      frameOffsetInFile_ += recordOffsetInFrame_;
       recordOffsetInFrame_ = 0;
     } else {
       RUNTIME_CHECK(handler, isUnformatted.has_value());
+      recordLength.reset();
       if (isUnformatted.value_or(false)) {
         // Retain footer in frame for more efficient BACKSPACE
-        frameOffsetInFile_ += recordOffsetInFrame_ + *recordLength;
+        frameOffsetInFile_ += recordOffsetInFrame_;
         recordOffsetInFrame_ = sizeof(std::uint32_t);
-        recordLength.reset();
       } else { // formatted
-        if (FrameLength() > recordOffsetInFrame_ + *recordLength &&
-            Frame()[recordOffsetInFrame_ + *recordLength] == '\r') {
+        if (FrameLength() > recordOffsetInFrame_ &&
+            Frame()[recordOffsetInFrame_] == '\r') {
           ++recordOffsetInFrame_;
         }
         if (FrameLength() >= recordOffsetInFrame_ &&
-            Frame()[recordOffsetInFrame_ + *recordLength] == '\n') {
+            Frame()[recordOffsetInFrame_] == '\n') {
           ++recordOffsetInFrame_;
         }
-        if (!resumptionRecordNumber || mayPosition()) {
-          frameOffsetInFile_ += recordOffsetInFrame_ + *recordLength;
+        if (!pinnedFrame || mayPosition()) {
+          frameOffsetInFile_ += recordOffsetInFrame_;
           recordOffsetInFrame_ = 0;
         }
-        recordLength.reset();
       }
     }
   }


        


More information about the flang-commits mailing list