Index: flang/runtime/connection.h =================================================================== --- flang/runtime/connection.h +++ flang/runtime/connection.h @@ -74,7 +74,7 @@ std::int64_t currentRecordNumber{1}; // 1 is first - // positionInRecord is the 0-based bytes offset in the current recurd + // positionInRecord is the 0-based bytes offset in the current record // to/from which the next data transfer will occur. It can be past // furthestPositionInRecord if moved by an X or T or TR control edit // descriptor. Index: flang/runtime/descriptor-io.cpp =================================================================== --- flang/runtime/descriptor-io.cpp +++ flang/runtime/descriptor-io.cpp @@ -50,6 +50,13 @@ int unit{external->unitNumber()}; int ioStat{IostatOk}; char ioMsg[100]; + std::optional startPos; + if (edit.descriptor == DataEdit::DefinedDerivedType && + special.which() == typeInfo::SpecialBinding::Which::ReadFormatted) { + // DT is an edit descriptor so everything that the child + // I/O subroutine reads counts towards READ(SIZE=). + startPos = io.InquirePos(); + } if (special.IsArgDescriptor(0)) { auto *p{special.GetProc()}; @@ -69,6 +76,9 @@ RUNTIME_CHECK(handler, external == closing); external->DestroyClosed(); } + if (startPos) { + io.GotChar(io.InquirePos() - *startPos); + } return handler.GetIoStat() == IostatOk; } else { // There's a user-defined I/O subroutine, but there's a FORMAT present and Index: flang/runtime/internal-unit.h =================================================================== --- flang/runtime/internal-unit.h +++ flang/runtime/internal-unit.h @@ -34,6 +34,7 @@ std::size_t GetNextInputBytes(const char *&, IoErrorHandler &); bool AdvanceRecord(IoErrorHandler &); void BackspaceRecord(IoErrorHandler &); + std::int64_t InquirePos(); private: Descriptor &descriptor() { return staticDescriptor_.descriptor(); } Index: flang/runtime/internal-unit.cpp =================================================================== --- flang/runtime/internal-unit.cpp +++ flang/runtime/internal-unit.cpp @@ -157,6 +157,12 @@ BeginRecord(); } +template +std::int64_t InternalDescriptorUnit::InquirePos() { + return (currentRecordNumber - 1) * recordLength.value_or(0) + + positionInRecord + 1; +} + template class InternalDescriptorUnit; template class InternalDescriptorUnit; } // namespace Fortran::runtime::io Index: flang/runtime/io-stmt.h =================================================================== --- flang/runtime/io-stmt.h +++ flang/runtime/io-stmt.h @@ -102,6 +102,7 @@ bool Inquire(InquiryKeywordHash, bool &); bool Inquire(InquiryKeywordHash, std::int64_t, bool &); // PENDING= bool Inquire(InquiryKeywordHash, std::int64_t &); + std::int64_t InquirePos(); void GotChar(signed int = 1); // for READ(SIZE=); can be <0 MutableModes &mutableModes(); @@ -262,6 +263,7 @@ bool Inquire(InquiryKeywordHash, bool &); bool Inquire(InquiryKeywordHash, std::int64_t, bool &); bool Inquire(InquiryKeywordHash, std::int64_t &); + std::int64_t InquirePos(); void BadInquiryKeywordHashCrash(InquiryKeywordHash); @@ -343,6 +345,7 @@ MutableModes &mutableModes() { return unit_.modes; } void HandleRelativePosition(std::int64_t); void HandleAbsolutePosition(std::int64_t); + std::int64_t InquirePos(); protected: bool free_{true}; @@ -406,6 +409,7 @@ int EndIoStatement(); ExternalFileUnit *GetExternalFileUnit() const { return &unit_; } void SetAsynchronous(); + std::int64_t InquirePos(); private: ExternalFileUnit &unit_; @@ -483,7 +487,6 @@ MutableModes &mutableModes(); ConnectionState &GetConnectionState(); ExternalFileUnit *GetExternalFileUnit() const; - void CompleteOperation(); int EndIoStatement(); bool Emit(const char *, std::size_t bytes, std::size_t elementBytes = 0); std::size_t GetNextInputBytes(const char *&); Index: flang/runtime/io-stmt.cpp =================================================================== --- flang/runtime/io-stmt.cpp +++ flang/runtime/io-stmt.cpp @@ -70,6 +70,8 @@ return false; } +std::int64_t IoStatementBase::InquirePos() { return 0; } + void IoStatementBase::BadInquiryKeywordHashCrash(InquiryKeywordHash inquiry) { char buffer[16]; const char *decode{InquiryKeywordHashDecode(buffer, sizeof buffer, inquiry)}; @@ -137,6 +139,11 @@ return unit_.HandleRelativePosition(n); } +template +std::int64_t InternalIoStatementState::InquirePos() { + return unit_.InquirePos(); +} + template InternalFormattedIoStatementState::InternalFormattedIoStatementState( Buffer buffer, std::size_t length, const CharType *format, @@ -206,6 +213,10 @@ asynchronousID_ = unit().GetAsynchronousId(*this); } +std::int64_t ExternalIoStatementBase::InquirePos() { + return unit_.InquirePos(); +} + void OpenStatementState::set_path(const char *path, std::size_t length) { pathLength_ = TrimTrailingSpaces(path, length); path_ = SaveDefaultCharacter(path, pathLength_, *this); @@ -635,6 +646,10 @@ [&](auto &x) { return x.get().Inquire(inquiry, n); }, u_); } +std::int64_t IoStatementState::InquirePos() { + return common::visit([&](auto &x) { return x.get().InquirePos(); }, u_); +} + void IoStatementState::GotChar(int n) { if (auto *formattedIn{ get_if>()}) { @@ -823,10 +838,6 @@ return child_.parent().GetExternalFileUnit(); } -template void ChildIoStatementState::CompleteOperation() { - IoStatementBase::CompleteOperation(); -} - template int ChildIoStatementState::EndIoStatement() { CompleteOperation(); auto result{IoStatementBase::EndIoStatement()};