From: peter klausler Date: Wed, 30 Sep 2020 19:53:00 +0000 (-0700) Subject: [flang] Allow record advancement in external formatted sequential READ X-Git-Tag: llvmorg-13-init~10447 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e24f0ac7a389fcb5c2f5295e717d9f7d3fcd4cea;p=platform%2Fupstream%2Fllvm.git [flang] Allow record advancement in external formatted sequential READ The '/' control edit descriptor causes a runtime crash for an external formatted sequential READ because the AdvanceRecord() member function for external units implemented only the tasks to finish reading the current record. Split those out into a new FinishReadingRecord() member function, call that instead from EndIoStatement(), and change AdvanceRecord() to both finish reading the current record and to begin reading the next one. Differential revision: https://reviews.llvm.org/D88607 --- diff --git a/flang/runtime/io-stmt.cpp b/flang/runtime/io-stmt.cpp index 9bf0284..2a7d552 100644 --- a/flang/runtime/io-stmt.cpp +++ b/flang/runtime/io-stmt.cpp @@ -236,11 +236,13 @@ int NoUnitIoStatementState::EndIoStatement() { template int ExternalIoStatementState::EndIoStatement() { if constexpr (DIR == Direction::Input) { BeginReadingRecord(); // in case of READ with no data items - } - if (!unit().nonAdvancing && GetIoStat() != IostatEnd) { - unit().AdvanceRecord(*this); - } - if constexpr (DIR == Direction::Output) { + if (!unit().nonAdvancing) { + FinishReadingRecord(); + } + } else { + if (!unit().nonAdvancing) { + unit().AdvanceRecord(*this); + } unit().FlushIfTerminal(*this); } return ExternalIoStatementBase::EndIoStatement(); @@ -315,10 +317,20 @@ void ExternalIoStatementState::HandleRelativePosition(std::int64_t n) { template void ExternalIoStatementState::BeginReadingRecord() { if constexpr (DIR == Direction::Input) { - if (!beganReading_) { - beganReading_ = true; - unit().BeginReadingRecord(*this); - } + unit().BeginReadingRecord(*this); + } else { + Crash("ExternalIoStatementState::BeginReadingRecord() " + "called"); + } +} + +template +void ExternalIoStatementState::FinishReadingRecord() { + if constexpr (DIR == Direction::Input) { + unit().FinishReadingRecord(*this); + } else { + Crash("ExternalIoStatementState::FinishReadingRecord() " + "called"); } } diff --git a/flang/runtime/io-stmt.h b/flang/runtime/io-stmt.h index 9e68dea..3c82dc8 100644 --- a/flang/runtime/io-stmt.h +++ b/flang/runtime/io-stmt.h @@ -65,6 +65,7 @@ public: ExternalFileUnit *GetExternalFileUnit() const; // null if internal unit MutableModes &mutableModes(); void BeginReadingRecord(); + void FinishReadingRecord(); bool Inquire(InquiryKeywordHash, char *, std::size_t); bool Inquire(InquiryKeywordHash, bool &); bool Inquire(InquiryKeywordHash, std::int64_t, bool &); // PENDING= @@ -123,7 +124,7 @@ struct IoStatementBase : public DefaultFormatControlCallbacks { std::optional GetNextDataEdit(IoStatementState &, int = 1); ExternalFileUnit *GetExternalFileUnit() const { return nullptr; } void BeginReadingRecord() {} - + void FinishReadingRecord() {} bool Inquire(InquiryKeywordHash, char *, std::size_t); bool Inquire(InquiryKeywordHash, bool &); bool Inquire(InquiryKeywordHash, std::int64_t, bool &); @@ -269,9 +270,7 @@ public: void HandleRelativePosition(std::int64_t); void HandleAbsolutePosition(std::int64_t); void BeginReadingRecord(); - -private: - bool beganReading_{false}; + void FinishReadingRecord(); }; template diff --git a/flang/runtime/unit.cpp b/flang/runtime/unit.cpp index be36666..8170fbc 100644 --- a/flang/runtime/unit.cpp +++ b/flang/runtime/unit.cpp @@ -349,6 +349,10 @@ void ExternalFileUnit::SetLeftTabLimit() { void ExternalFileUnit::BeginReadingRecord(IoErrorHandler &handler) { RUNTIME_CHECK(handler, direction_ == Direction::Input); + if (beganReadingRecord_) { + return; + } + beganReadingRecord_ = true; if (access == Access::Sequential) { if (endfileRecordNumber && currentRecordNumber >= *endfileRecordNumber) { handler.SignalEnd(); @@ -367,28 +371,37 @@ void ExternalFileUnit::BeginReadingRecord(IoErrorHandler &handler) { } } +void ExternalFileUnit::FinishReadingRecord(IoErrorHandler &handler) { + RUNTIME_CHECK(handler, direction_ == Direction::Input && beganReadingRecord_); + beganReadingRecord_ = false; + if (access == Access::Sequential) { + RUNTIME_CHECK(handler, recordLength.has_value()); + if (isFixedRecordLength) { + frameOffsetInFile_ += recordOffsetInFrame_ + *recordLength; + recordOffsetInFrame_ = 0; + } else if (isUnformatted) { + // Retain footer in frame for more efficient BACKSPACE + frameOffsetInFile_ += recordOffsetInFrame_ + *recordLength; + recordOffsetInFrame_ = sizeof(std::uint32_t); + recordLength.reset(); + } else { // formatted + if (Frame()[recordOffsetInFrame_ + *recordLength] == '\r') { + ++recordOffsetInFrame_; + } + recordOffsetInFrame_ += *recordLength + 1; + RUNTIME_CHECK(handler, Frame()[recordOffsetInFrame_ - 1] == '\n'); + recordLength.reset(); + } + } + ++currentRecordNumber; + BeginRecord(); +} + bool ExternalFileUnit::AdvanceRecord(IoErrorHandler &handler) { bool ok{true}; if (direction_ == Direction::Input) { - if (access == Access::Sequential) { - RUNTIME_CHECK(handler, recordLength.has_value()); - if (isFixedRecordLength) { - frameOffsetInFile_ += recordOffsetInFrame_ + *recordLength; - recordOffsetInFrame_ = 0; - } else if (isUnformatted) { - // Retain footer in frame for more efficient BACKSPACE - frameOffsetInFile_ += recordOffsetInFrame_ + *recordLength; - recordOffsetInFrame_ = sizeof(std::uint32_t); - recordLength.reset(); - } else { // formatted - if (Frame()[recordOffsetInFrame_ + *recordLength] == '\r') { - ++recordOffsetInFrame_; - } - recordOffsetInFrame_ += *recordLength + 1; - RUNTIME_CHECK(handler, Frame()[recordOffsetInFrame_ - 1] == '\n'); - recordLength.reset(); - } - } + FinishReadingRecord(handler); + BeginReadingRecord(handler); } else { // Direction::Output if (!isUnformatted) { if (isFixedRecordLength && recordLength) { @@ -406,9 +419,9 @@ bool ExternalFileUnit::AdvanceRecord(IoErrorHandler &handler) { recordOffsetInFrame_ + recordLength.value_or(furthestPositionInRecord); recordOffsetInFrame_ = 0; impliedEndfile_ = true; + ++currentRecordNumber; + BeginRecord(); } - ++currentRecordNumber; - BeginRecord(); return ok; } diff --git a/flang/runtime/unit.h b/flang/runtime/unit.h index 9d66d96..644ca4a 100644 --- a/flang/runtime/unit.h +++ b/flang/runtime/unit.h @@ -78,6 +78,7 @@ public: std::optional GetCurrentChar(IoErrorHandler &); void SetLeftTabLimit(); void BeginReadingRecord(IoErrorHandler &); + void FinishReadingRecord(IoErrorHandler &); bool AdvanceRecord(IoErrorHandler &); void BackspaceRecord(IoErrorHandler &); void FlushIfTerminal(IoErrorHandler &); @@ -105,6 +106,7 @@ private: int unitNumber_{-1}; Direction direction_{Direction::Output}; bool impliedEndfile_{false}; // seq. output has taken place + bool beganReadingRecord_{false}; Lock lock_;