aboutsummaryrefslogtreecommitdiff
path: root/flang
diff options
context:
space:
mode:
authorPeter Klausler <35819229+klausler@users.noreply.github.com>2024-06-24 10:34:37 -0700
committerGitHub <noreply@github.com>2024-06-24 10:34:37 -0700
commiteac925fb81f26342811ad1765e8f9919628e2254 (patch)
tree39797429609b919ca92732f2af7ac79d034cc6d7 /flang
parente6ec3664cb72fd95669cb516b21572da4236fd91 (diff)
downloadllvm-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.cpp18
-rw-r--r--flang/runtime/pseudo-unit.cpp2
-rw-r--r--flang/runtime/unit.h2
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();