From dfea011a37797f77ef526880694254cb6e655a8e Mon Sep 17 00:00:00 2001 From: peter klausler Date: Mon, 16 Aug 2021 13:15:01 -0700 Subject: [PATCH] [flang] Fix regression from recent runtime input fix A recent runtime I/O change[1] was meant to improve the handling of input from external files missing a terminal newline on their last records; the change was "triggered" by the wrong circumstances and causing reads that should have pulled more data into the buffer to be treated as EOFs. So fix that, and also don't retain input data in the buffer once an input record has been finished unless it's known that list-directed or NAMELIST input of a repeated input item may need to backspace a non-positionable external unit to return to the beginning of the repeated item. [1] 6578893a0453384346f149479f8574dfff977ace Differential Revision: https://reviews.llvm.org/D108164 --- flang/runtime/connection.h | 6 ++++++ flang/runtime/io-stmt.cpp | 15 +++++++++++++-- flang/runtime/io-stmt.h | 1 - flang/runtime/unit.cpp | 25 ++++++++++++++++--------- 4 files changed, 35 insertions(+), 12 deletions(-) diff --git a/flang/runtime/connection.h b/flang/runtime/connection.h index 6d0678f..3a2f303 100644 --- a/flang/runtime/connection.h +++ b/flang/runtime/connection.h @@ -57,6 +57,12 @@ struct ConnectionState : public ConnectionAttributes { // or an end-of-file READ condition on a sequential access file std::optional endfileRecordNumber; + // 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 resumptionRecordNumber; + // Mutable modes set at OPEN() that can be overridden in READ/WRITE & FORMAT MutableModes modes; // BLANK=, DECIMAL=, SIGN=, ROUND=, PAD=, DELIM=, kP }; diff --git a/flang/runtime/io-stmt.cpp b/flang/runtime/io-stmt.cpp index 084fc78..fc1dcbf 100644 --- a/flang/runtime/io-stmt.cpp +++ b/flang/runtime/io-stmt.cpp @@ -653,7 +653,11 @@ ListDirectedStatementState::GetNextDataEdit( comma = ';'; } if (remaining_ > 0 && !realPart_) { // "r*c" repetition in progress - while (connection.currentRecordNumber > repeatRecordNumber_) { + RUNTIME_CHECK( + io.GetIoErrorHandler(), connection.resumptionRecordNumber.has_value()); + while (connection.currentRecordNumber > + connection.resumptionRecordNumber.value_or( + connection.currentRecordNumber)) { io.BackspaceRecord(); } connection.HandleAbsolutePosition(repeatPositionInRecord_); @@ -666,6 +670,9 @@ ListDirectedStatementState::GetNextDataEdit( } } remaining_ -= edit.repeat; + if (remaining_ <= 0) { + connection.resumptionRecordNumber.reset(); + } return edit; } // Skip separators, handle a "r*c" repeat count; see 13.10.2 in Fortran 2018 @@ -726,7 +733,11 @@ ListDirectedStatementState::GetNextDataEdit( } edit.repeat = std::min(r, maxRepeat); remaining_ = r - edit.repeat; - repeatRecordNumber_ = connection.currentRecordNumber; + if (remaining_ > 0) { + connection.resumptionRecordNumber = connection.currentRecordNumber; + } else { + connection.resumptionRecordNumber.reset(); + } 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 cfbafe2..32aeae0 100644 --- a/flang/runtime/io-stmt.h +++ b/flang/runtime/io-stmt.h @@ -229,7 +229,6 @@ public: private: int remaining_{0}; // for "r*" repetition - std::int64_t repeatRecordNumber_; std::int64_t repeatPositionInRecord_; bool eatComma_{false}; // consume comma after previously read item bool hitSlash_{false}; // once '/' is seen, nullify further items diff --git a/flang/runtime/unit.cpp b/flang/runtime/unit.cpp index b36acf4..55304a8 100644 --- a/flang/runtime/unit.cpp +++ b/flang/runtime/unit.cpp @@ -350,13 +350,10 @@ bool ExternalFileUnit::SetSequentialVariableFormattedRecordLength() { if (*recordLength > 0 && record[*recordLength - 1] == '\r') { --*recordLength; } - } else { - recordLength = bytes; // final record w/o \n + return true; } - return true; - } else { - return false; } + return false; } void ExternalFileUnit::SetLeftTabLimit() { @@ -421,7 +418,10 @@ void ExternalFileUnit::FinishReadingRecord(IoErrorHandler &handler) { Frame()[recordOffsetInFrame_ + *recordLength] == '\n') { ++recordOffsetInFrame_; } - recordOffsetInFrame_ += *recordLength; + if (!resumptionRecordNumber || mayPosition()) { + frameOffsetInFile_ += recordOffsetInFrame_ + *recordLength; + recordOffsetInFrame_ = 0; + } recordLength.reset(); } } @@ -612,10 +612,17 @@ void ExternalFileUnit::BeginSequentialVariableFormattedInputRecord( } std::size_t length{0}; do { - std::size_t need{recordOffsetInFrame_ + length + 1}; - length = ReadFrame(frameOffsetInFile_, need, handler); + std::size_t need{length + 1}; + length = + ReadFrame(frameOffsetInFile_, recordOffsetInFrame_ + need, handler) - + recordOffsetInFrame_; if (length < need) { - handler.SignalEnd(); + if (length > 0) { + // final record w/o \n + recordLength = length; + } else { + handler.SignalEnd(); + } break; } } while (!SetSequentialVariableFormattedRecordLength()); -- 2.7.4