[flang-commits] [flang] e24f0ac - [flang] Allow record advancement in external formatted sequential READ
peter klausler via flang-commits
flang-commits at lists.llvm.org
Wed Sep 30 17:17:23 PDT 2020
Author: peter klausler
Date: 2020-09-30T17:16:55-07:00
New Revision: e24f0ac7a389fcb5c2f5295e717d9f7d3fcd4cea
URL: https://github.com/llvm/llvm-project/commit/e24f0ac7a389fcb5c2f5295e717d9f7d3fcd4cea
DIFF: https://github.com/llvm/llvm-project/commit/e24f0ac7a389fcb5c2f5295e717d9f7d3fcd4cea.diff
LOG: [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
Added:
Modified:
flang/runtime/io-stmt.cpp
flang/runtime/io-stmt.h
flang/runtime/unit.cpp
flang/runtime/unit.h
Removed:
################################################################################
diff --git a/flang/runtime/io-stmt.cpp b/flang/runtime/io-stmt.cpp
index 9bf0284358b9..2a7d552dacd8 100644
--- a/flang/runtime/io-stmt.cpp
+++ b/flang/runtime/io-stmt.cpp
@@ -236,11 +236,13 @@ int NoUnitIoStatementState::EndIoStatement() {
template <Direction DIR> int ExternalIoStatementState<DIR>::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<DIR>::HandleRelativePosition(std::int64_t n) {
template <Direction DIR>
void ExternalIoStatementState<DIR>::BeginReadingRecord() {
if constexpr (DIR == Direction::Input) {
- if (!beganReading_) {
- beganReading_ = true;
- unit().BeginReadingRecord(*this);
- }
+ unit().BeginReadingRecord(*this);
+ } else {
+ Crash("ExternalIoStatementState<Direction::Output>::BeginReadingRecord() "
+ "called");
+ }
+}
+
+template <Direction DIR>
+void ExternalIoStatementState<DIR>::FinishReadingRecord() {
+ if constexpr (DIR == Direction::Input) {
+ unit().FinishReadingRecord(*this);
+ } else {
+ Crash("ExternalIoStatementState<Direction::Output>::FinishReadingRecord() "
+ "called");
}
}
diff --git a/flang/runtime/io-stmt.h b/flang/runtime/io-stmt.h
index 9e68deab2e64..3c82dc8b1b0a 100644
--- a/flang/runtime/io-stmt.h
+++ b/flang/runtime/io-stmt.h
@@ -65,6 +65,7 @@ class IoStatementState {
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<DataEdit> 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 @@ class ExternalIoStatementState : public ExternalIoStatementBase,
void HandleRelativePosition(std::int64_t);
void HandleAbsolutePosition(std::int64_t);
void BeginReadingRecord();
-
-private:
- bool beganReading_{false};
+ void FinishReadingRecord();
};
template <Direction DIR, typename CHAR>
diff --git a/flang/runtime/unit.cpp b/flang/runtime/unit.cpp
index be36666f66e4..8170fbc696c2 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 9d66d962bc56..644ca4ad63cc 100644
--- a/flang/runtime/unit.h
+++ b/flang/runtime/unit.h
@@ -78,6 +78,7 @@ class ExternalFileUnit : public ConnectionState,
std::optional<char32_t> GetCurrentChar(IoErrorHandler &);
void SetLeftTabLimit();
void BeginReadingRecord(IoErrorHandler &);
+ void FinishReadingRecord(IoErrorHandler &);
bool AdvanceRecord(IoErrorHandler &);
void BackspaceRecord(IoErrorHandler &);
void FlushIfTerminal(IoErrorHandler &);
@@ -105,6 +106,7 @@ class ExternalFileUnit : public ConnectionState,
int unitNumber_{-1};
Direction direction_{Direction::Output};
bool impliedEndfile_{false}; // seq. output has taken place
+ bool beganReadingRecord_{false};
Lock lock_;
More information about the flang-commits
mailing list