Skip to content

Commit ccc573c

Browse files
authored
[flang][runtime] When OPEN implies CLOSE, disable later extant unit c… (#69390)
…hecks An OPEN statement on an existing unit can imply a CLOSE of that unit; for example, OPEN(5, FILE="mydata", FORM="formatted") should implicitly close the standard input that had been preconnected to unit 5. When this happens, later checks in OPEN statement completion that apply only to existing units should be disabled.
1 parent 483e924 commit ccc573c

File tree

3 files changed

+13
-7
lines changed

3 files changed

+13
-7
lines changed

flang/runtime/io-stmt.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -248,8 +248,10 @@ void OpenStatementState::CompleteOperation() {
248248
}
249249
if (path_.get() || wasExtant_ ||
250250
(status_ && *status_ == OpenStatus::Scratch)) {
251-
unit().OpenUnit(status_, action_, position_.value_or(Position::AsIs),
252-
std::move(path_), pathLength_, convert_, *this);
251+
if (unit().OpenUnit(status_, action_, position_.value_or(Position::AsIs),
252+
std::move(path_), pathLength_, convert_, *this)) {
253+
wasExtant_ = false; // existing unit was closed
254+
}
253255
} else {
254256
unit().OpenAnonymousUnit(
255257
status_, action_, position_.value_or(Position::AsIs), convert_, *this);

flang/runtime/unit.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ ExternalFileUnit &ExternalFileUnit::NewUnit(
9090
return unit;
9191
}
9292

93-
void ExternalFileUnit::OpenUnit(std::optional<OpenStatus> status,
93+
bool ExternalFileUnit::OpenUnit(std::optional<OpenStatus> status,
9494
std::optional<Action> action, Position position, OwningPtr<char> &&newPath,
9595
std::size_t newPathLength, Convert convert, IoErrorHandler &handler) {
9696
if (convert == Convert::Unknown) {
@@ -99,24 +99,26 @@ void ExternalFileUnit::OpenUnit(std::optional<OpenStatus> status,
9999
swapEndianness_ = convert == Convert::Swap ||
100100
(convert == Convert::LittleEndian && !isHostLittleEndian) ||
101101
(convert == Convert::BigEndian && isHostLittleEndian);
102+
bool impliedClose{false};
102103
if (IsConnected()) {
103104
bool isSamePath{newPath.get() && path() && pathLength() == newPathLength &&
104105
std::memcmp(path(), newPath.get(), newPathLength) == 0};
105106
if (status && *status != OpenStatus::Old && isSamePath) {
106107
handler.SignalError("OPEN statement for connected unit may not have "
107108
"explicit STATUS= other than 'OLD'");
108-
return;
109+
return impliedClose;
109110
}
110111
if (!newPath.get() || isSamePath) {
111112
// OPEN of existing unit, STATUS='OLD' or unspecified, not new FILE=
112113
newPath.reset();
113-
return;
114+
return impliedClose;
114115
}
115116
// Otherwise, OPEN on open unit with new FILE= implies CLOSE
116117
DoImpliedEndfile(handler);
117118
FlushOutput(handler);
118119
TruncateFrame(0, handler);
119120
Close(CloseStatus::Keep, handler);
121+
impliedClose = true;
120122
}
121123
if (newPath.get() && newPathLength > 0) {
122124
if (const auto *already{
@@ -125,7 +127,7 @@ void ExternalFileUnit::OpenUnit(std::optional<OpenStatus> status,
125127
"OPEN(UNIT=%d,FILE='%.*s'): file is already connected to unit %d",
126128
unitNumber_, static_cast<int>(newPathLength), newPath.get(),
127129
already->unitNumber_);
128-
return;
130+
return impliedClose;
129131
}
130132
}
131133
set_path(std::move(newPath), newPathLength);
@@ -166,6 +168,7 @@ void ExternalFileUnit::OpenUnit(std::optional<OpenStatus> status,
166168
currentRecordNumber = *endfileRecordNumber;
167169
}
168170
}
171+
return impliedClose;
169172
}
170173

171174
void ExternalFileUnit::OpenAnonymousUnit(std::optional<OpenStatus> status,

flang/runtime/unit.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ class ExternalFileUnit : public ConnectionState,
5959
static void CloseAll(IoErrorHandler &);
6060
static void FlushAll(IoErrorHandler &);
6161

62-
void OpenUnit(std::optional<OpenStatus>, std::optional<Action>, Position,
62+
// Returns true if an existing unit was closed
63+
bool OpenUnit(std::optional<OpenStatus>, std::optional<Action>, Position,
6364
OwningPtr<char> &&path, std::size_t pathLength, Convert,
6465
IoErrorHandler &);
6566
void OpenAnonymousUnit(std::optional<OpenStatus>, std::optional<Action>,

0 commit comments

Comments
 (0)