diff --git a/flang/runtime/io-api.cpp b/flang/runtime/io-api.cpp --- a/flang/runtime/io-api.cpp +++ b/flang/runtime/io-api.cpp @@ -149,9 +149,6 @@ unit.SetDirection(DIR, handler); IoStatementState &io{unit.BeginIoStatement>( unit, sourceFile, sourceLine)}; - if constexpr (DIR == Direction::Input) { - unit.BeginReadingRecord(handler); - } return &io; } @@ -185,9 +182,6 @@ IoStatementState &io{ unit.BeginIoStatement>( unit, format, formatLength, sourceFile, sourceLine)}; - if constexpr (DIR == Direction::Input) { - unit.BeginReadingRecord(handler); - } return &io; } @@ -218,9 +212,7 @@ unit, sourceFile, sourceLine)}; IoErrorHandler handler{terminator}; unit.SetDirection(DIR, handler); - if constexpr (DIR == Direction::Input) { - unit.BeginReadingRecord(handler); - } else { + if constexpr (DIR == Direction::Output) { if (unit.access == Access::Sequential && !unit.isFixedRecordLength) { // Create space for (sub)record header to be completed by // UnformattedIoStatementState::EndIoStatement() @@ -838,6 +830,7 @@ bool IONAME(InputDescriptor)(Cookie cookie, const Descriptor &) { IoStatementState &io{*cookie}; + io.BeginReadingRecord(); io.GetIoErrorHandler().Crash("InputDescriptor: not yet implemented"); // TODO } @@ -855,6 +848,7 @@ bool IONAME(InputUnformattedBlock)( Cookie cookie, char *x, std::size_t length, std::size_t elementBytes) { IoStatementState &io{*cookie}; + io.BeginReadingRecord(); if (auto *unf{io.get_if>()}) { return unf->Receive(x, length, elementBytes); } @@ -883,6 +877,7 @@ "InputInteger64() called for a non-input I/O statement"); return false; } + io.BeginReadingRecord(); if (auto edit{io.GetNextDataEdit()}) { if (edit->descriptor == DataEdit::ListDirectedNullValue) { return true; @@ -922,6 +917,7 @@ "InputReal() called for a non-input I/O statement"); return false; } + io.BeginReadingRecord(); if (auto edit{io.GetNextDataEdit()}) { if (edit->descriptor == DataEdit::ListDirectedNullValue) { return true; @@ -968,6 +964,7 @@ "InputComplex() called for a non-input I/O statement"); return false; } + io.BeginReadingRecord(); for (int j{0}; j < 2; ++j) { if (auto edit{io.GetNextDataEdit()}) { if (edit->descriptor == DataEdit::ListDirectedNullValue) { @@ -1012,6 +1009,7 @@ "InputAscii() called for a non-input I/O statement"); return false; } + io.BeginReadingRecord(); if (auto edit{io.GetNextDataEdit()}) { if (edit->descriptor == DataEdit::ListDirectedNullValue) { return true; @@ -1044,6 +1042,7 @@ "InputLogical() called for a non-input I/O statement"); return false; } + io.BeginReadingRecord(); if (auto edit{io.GetNextDataEdit()}) { if (edit->descriptor == DataEdit::ListDirectedNullValue) { return true; diff --git a/flang/runtime/io-stmt.h b/flang/runtime/io-stmt.h --- a/flang/runtime/io-stmt.h +++ b/flang/runtime/io-stmt.h @@ -59,6 +59,7 @@ IoErrorHandler &GetIoErrorHandler() const; ExternalFileUnit *GetExternalFileUnit() const; // null if internal unit MutableModes &mutableModes(); + void BeginReadingRecord(); // N.B.: this also works with base classes template A *get_if() const { @@ -108,6 +109,7 @@ int EndIoStatement(); std::optional GetNextDataEdit(IoStatementState &, int = 1); ExternalFileUnit *GetExternalFileUnit() const { return nullptr; } + void BeginReadingRecord() {} }; struct InputStatementState {}; @@ -247,6 +249,10 @@ void BackspaceRecord(); void HandleRelativePosition(std::int64_t); void HandleAbsolutePosition(std::int64_t); + void BeginReadingRecord(); + +private: + bool beganReading_{false}; }; template diff --git a/flang/runtime/io-stmt.cpp b/flang/runtime/io-stmt.cpp --- a/flang/runtime/io-stmt.cpp +++ b/flang/runtime/io-stmt.cpp @@ -185,7 +185,10 @@ } template int ExternalIoStatementState::EndIoStatement() { - if (!unit().nonAdvancing) { + 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) { @@ -260,6 +263,16 @@ return unit().HandleRelativePosition(n); } +template +void ExternalIoStatementState::BeginReadingRecord() { + if constexpr (DIR == Direction::Input) { + if (!beganReading_) { + beganReading_ = true; + unit().BeginReadingRecord(*this); + } + } +} + template ExternalFormattedIoStatementState::ExternalFormattedIoStatementState( ExternalFileUnit &unit, const CHAR *format, std::size_t formatLength, @@ -315,6 +328,10 @@ [](auto &x) -> MutableModes & { return x.get().mutableModes(); }, u_); } +void IoStatementState::BeginReadingRecord() { + std::visit([](auto &x) { return x.get().BeginReadingRecord(); }, u_); +} + IoErrorHandler &IoStatementState::GetIoErrorHandler() const { return std::visit( [](auto &x) -> IoErrorHandler & {