diff options
author | Peter Klausler <35819229+klausler@users.noreply.github.com> | 2024-06-24 10:34:37 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-24 10:34:37 -0700 |
commit | eac925fb81f26342811ad1765e8f9919628e2254 (patch) | |
tree | 39797429609b919ca92732f2af7ac79d034cc6d7 /flang | |
parent | e6ec3664cb72fd95669cb516b21572da4236fd91 (diff) | |
download | llvm-eac925fb81f26342811ad1765e8f9919628e2254.zip llvm-eac925fb81f26342811ad1765e8f9919628e2254.tar.gz llvm-eac925fb81f26342811ad1765e8f9919628e2254.tar.bz2 |
[flang][runtime] Better handling of "fort.N" opening errors (#96347)
When a data transfer statement references a unit number that hasn't been
explicitly OPENed, the runtime I/O support library opens a local
"fort.N" file where N is the unit number. If that name exists in the
current working directory but is not a readable or writable file (as
appropriate), the runtime needs to catch the error at the point of the
READ or WRITE statement rather than leaving an open unit in the unit map
without a valid file descriptor.
Diffstat (limited to 'flang')
-rw-r--r-- | flang/runtime/external-unit.cpp | 18 | ||||
-rw-r--r-- | flang/runtime/pseudo-unit.cpp | 2 | ||||
-rw-r--r-- | flang/runtime/unit.h | 2 |
3 files changed, 15 insertions, 7 deletions
diff --git a/flang/runtime/external-unit.cpp b/flang/runtime/external-unit.cpp index 328c994..8009151 100644 --- a/flang/runtime/external-unit.cpp +++ b/flang/runtime/external-unit.cpp @@ -65,10 +65,17 @@ ExternalFileUnit *ExternalFileUnit::LookUpOrCreateAnonymous(int unit, bool exists{false}; ExternalFileUnit *result{GetUnitMap().LookUpOrCreate(unit, handler, exists)}; if (result && !exists) { - result->OpenAnonymousUnit( - dir == Direction::Input ? OpenStatus::Unknown : OpenStatus::Replace, - Action::ReadWrite, Position::Rewind, Convert::Unknown, handler); - result->isUnformatted = isUnformatted; + if (!result->OpenAnonymousUnit( + dir == Direction::Input ? OpenStatus::Unknown : OpenStatus::Replace, + Action::ReadWrite, Position::Rewind, Convert::Unknown, handler)) { + // fort.N isn't a writable file + if (ExternalFileUnit * closed{LookUpForClose(result->unitNumber())}) { + closed->DestroyClosed(); + } + result = nullptr; + } else { + result->isUnformatted = isUnformatted; + } } return result; } @@ -183,7 +190,7 @@ bool ExternalFileUnit::OpenUnit(Fortran::common::optional<OpenStatus> status, return impliedClose; } -void ExternalFileUnit::OpenAnonymousUnit( +bool ExternalFileUnit::OpenAnonymousUnit( Fortran::common::optional<OpenStatus> status, Fortran::common::optional<Action> action, Position position, Convert convert, IoErrorHandler &handler) { @@ -193,6 +200,7 @@ void ExternalFileUnit::OpenAnonymousUnit( std::snprintf(path.get(), pathMaxLen, "fort.%d", unitNumber_); OpenUnit(status, action, position, std::move(path), std::strlen(path.get()), convert, handler); + return IsConnected(); } void ExternalFileUnit::CloseUnit(CloseStatus status, IoErrorHandler &handler) { diff --git a/flang/runtime/pseudo-unit.cpp b/flang/runtime/pseudo-unit.cpp index 70e70ee..526afd1 100644 --- a/flang/runtime/pseudo-unit.cpp +++ b/flang/runtime/pseudo-unit.cpp @@ -65,7 +65,7 @@ bool ExternalFileUnit::OpenUnit(Fortran::common::optional<OpenStatus> status, handler.Crash("%s: unsupported", RT_PRETTY_FUNCTION); } -void ExternalFileUnit::OpenAnonymousUnit(Fortran::common::optional<OpenStatus>, +bool ExternalFileUnit::OpenAnonymousUnit(Fortran::common::optional<OpenStatus>, Fortran::common::optional<Action>, Position, Convert convert, IoErrorHandler &handler) { handler.Crash("%s: unsupported", RT_PRETTY_FUNCTION); diff --git a/flang/runtime/unit.h b/flang/runtime/unit.h index abd535f..83f839e 100644 --- a/flang/runtime/unit.h +++ b/flang/runtime/unit.h @@ -134,7 +134,7 @@ public: RT_API_ATTRS bool OpenUnit(Fortran::common::optional<OpenStatus>, Fortran::common::optional<Action>, Position, OwningPtr<char> &&path, std::size_t pathLength, Convert, IoErrorHandler &); - RT_API_ATTRS void OpenAnonymousUnit(Fortran::common::optional<OpenStatus>, + RT_API_ATTRS bool OpenAnonymousUnit(Fortran::common::optional<OpenStatus>, Fortran::common::optional<Action>, Position, Convert, IoErrorHandler &); RT_API_ATTRS void CloseUnit(CloseStatus, IoErrorHandler &); RT_API_ATTRS void DestroyClosed(); |