[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.
This commit is contained in:
Peter Klausler
2024-06-24 10:34:37 -07:00
committed by GitHub
parent e6ec3664cb
commit eac925fb81
3 changed files with 15 additions and 7 deletions

View File

@@ -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) {

View File

@@ -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);

View File

@@ -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();