diff --git a/flang/runtime/io-stmt.cpp b/flang/runtime/io-stmt.cpp index 1d951a4157d31..dedf1f8364ad3 100644 --- a/flang/runtime/io-stmt.cpp +++ b/flang/runtime/io-stmt.cpp @@ -248,8 +248,10 @@ void OpenStatementState::CompleteOperation() { } if (path_.get() || wasExtant_ || (status_ && *status_ == OpenStatus::Scratch)) { - unit().OpenUnit(status_, action_, position_.value_or(Position::AsIs), - std::move(path_), pathLength_, convert_, *this); + if (unit().OpenUnit(status_, action_, position_.value_or(Position::AsIs), + std::move(path_), pathLength_, convert_, *this)) { + wasExtant_ = false; // existing unit was closed + } } else { unit().OpenAnonymousUnit( status_, action_, position_.value_or(Position::AsIs), convert_, *this); diff --git a/flang/runtime/unit.cpp b/flang/runtime/unit.cpp index 1c8432328848e..dec8d8032f615 100644 --- a/flang/runtime/unit.cpp +++ b/flang/runtime/unit.cpp @@ -90,7 +90,7 @@ ExternalFileUnit &ExternalFileUnit::NewUnit( return unit; } -void ExternalFileUnit::OpenUnit(std::optional status, +bool ExternalFileUnit::OpenUnit(std::optional status, std::optional action, Position position, OwningPtr &&newPath, std::size_t newPathLength, Convert convert, IoErrorHandler &handler) { if (convert == Convert::Unknown) { @@ -99,24 +99,26 @@ void ExternalFileUnit::OpenUnit(std::optional status, swapEndianness_ = convert == Convert::Swap || (convert == Convert::LittleEndian && !isHostLittleEndian) || (convert == Convert::BigEndian && isHostLittleEndian); + bool impliedClose{false}; if (IsConnected()) { bool isSamePath{newPath.get() && path() && pathLength() == newPathLength && std::memcmp(path(), newPath.get(), newPathLength) == 0}; if (status && *status != OpenStatus::Old && isSamePath) { handler.SignalError("OPEN statement for connected unit may not have " "explicit STATUS= other than 'OLD'"); - return; + return impliedClose; } if (!newPath.get() || isSamePath) { // OPEN of existing unit, STATUS='OLD' or unspecified, not new FILE= newPath.reset(); - return; + return impliedClose; } // Otherwise, OPEN on open unit with new FILE= implies CLOSE DoImpliedEndfile(handler); FlushOutput(handler); TruncateFrame(0, handler); Close(CloseStatus::Keep, handler); + impliedClose = true; } if (newPath.get() && newPathLength > 0) { if (const auto *already{ @@ -125,7 +127,7 @@ void ExternalFileUnit::OpenUnit(std::optional status, "OPEN(UNIT=%d,FILE='%.*s'): file is already connected to unit %d", unitNumber_, static_cast(newPathLength), newPath.get(), already->unitNumber_); - return; + return impliedClose; } } set_path(std::move(newPath), newPathLength); @@ -166,6 +168,7 @@ void ExternalFileUnit::OpenUnit(std::optional status, currentRecordNumber = *endfileRecordNumber; } } + return impliedClose; } void ExternalFileUnit::OpenAnonymousUnit(std::optional status, diff --git a/flang/runtime/unit.h b/flang/runtime/unit.h index b6007a9b15385..1ec3013ba82b3 100644 --- a/flang/runtime/unit.h +++ b/flang/runtime/unit.h @@ -59,7 +59,8 @@ class ExternalFileUnit : public ConnectionState, static void CloseAll(IoErrorHandler &); static void FlushAll(IoErrorHandler &); - void OpenUnit(std::optional, std::optional, Position, + // Returns true if an existing unit was closed + bool OpenUnit(std::optional, std::optional, Position, OwningPtr &&path, std::size_t pathLength, Convert, IoErrorHandler &); void OpenAnonymousUnit(std::optional, std::optional,