diff --git a/flang/include/flang/Runtime/iostat.h b/flang/include/flang/Runtime/iostat.h --- a/flang/include/flang/Runtime/iostat.h +++ b/flang/include/flang/Runtime/iostat.h @@ -79,6 +79,7 @@ IostatCannotReposition, IostatBadWaitId, IostatTooManyAsyncOps, + IostatBadBackspaceUnit, }; const char *IostatErrorString(int); 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 @@ -395,10 +395,17 @@ Cookie IONAME(BeginBackspace)( ExternalUnit unitNumber, const char *sourceFile, int sourceLine) { Terminator terminator{sourceFile, sourceLine}; - ExternalFileUnit &unit{ - ExternalFileUnit::LookUpOrCrash(unitNumber, terminator)}; - return &unit.BeginIoStatement( - unit, ExternalMiscIoStatementState::Backspace, sourceFile, sourceLine); + if (ExternalFileUnit * unit{ExternalFileUnit::LookUp(unitNumber)}) { + return &unit->BeginIoStatement( + *unit, ExternalMiscIoStatementState::Backspace, sourceFile, sourceLine); + } else { + auto &io{ + New{terminator}(sourceFile, sourceLine, unitNumber) + .release() + ->ioStatementState()}; + io.GetIoErrorHandler().SetPendingError(IostatBadBackspaceUnit); + return &io; + } } Cookie IONAME(BeginEndfile)( 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 @@ -590,7 +590,8 @@ CloseStatus status_{CloseStatus::Keep}; }; -// For CLOSE(bad unit), WAIT(bad unit, ID=nonzero) and INQUIRE(unconnected unit) +// For CLOSE(bad unit), WAIT(bad unit, ID=nonzero), INQUIRE(unconnected unit), +// and recoverable BACKSPACE(bad unit) class NoUnitIoStatementState : public IoStatementBase { public: IoStatementState &ioStatementState() { return ioStatementState_; } 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 @@ -287,6 +287,7 @@ } void NoUnitIoStatementState::CompleteOperation() { + SignalPendingError(); IoStatementBase::CompleteOperation(); } diff --git a/flang/runtime/iostat.cpp b/flang/runtime/iostat.cpp --- a/flang/runtime/iostat.cpp +++ b/flang/runtime/iostat.cpp @@ -103,6 +103,8 @@ return "WAIT(ID=nonzero) for an ID value that is not a pending operation"; case IostatTooManyAsyncOps: return "Too many asynchronous operations pending on unit"; + case IostatBadBackspaceUnit: + return "BACKSPACE on unconnected unit"; default: return nullptr; } diff --git a/flang/runtime/unit.h b/flang/runtime/unit.h --- a/flang/runtime/unit.h +++ b/flang/runtime/unit.h @@ -47,7 +47,6 @@ bool createdForInternalChildIo() const { return createdForInternalChildIo_; } static ExternalFileUnit *LookUp(int unit); - static ExternalFileUnit &LookUpOrCrash(int unit, const Terminator &); static ExternalFileUnit &LookUpOrCreate( int unit, const Terminator &, bool &wasExtant); static ExternalFileUnit &LookUpOrCreateAnonymous(int unit, Direction, diff --git a/flang/runtime/unit.cpp b/flang/runtime/unit.cpp --- a/flang/runtime/unit.cpp +++ b/flang/runtime/unit.cpp @@ -43,15 +43,6 @@ return GetUnitMap().LookUp(unit); } -ExternalFileUnit &ExternalFileUnit::LookUpOrCrash( - int unit, const Terminator &terminator) { - ExternalFileUnit *file{LookUp(unit)}; - if (!file) { - terminator.Crash("%d is not an open I/O unit number", unit); - } - return *file; -} - ExternalFileUnit &ExternalFileUnit::LookUpOrCreate( int unit, const Terminator &terminator, bool &wasExtant) { return GetUnitMap().LookUpOrCreate(unit, terminator, wasExtant);