mirror of
https://github.com/intel/llvm.git
synced 2026-01-20 10:58:11 +08:00
[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:
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user