[llvm] [flang][runtime] OPEN(existingUnit,POSITION=) (PR #153688)
Peter Klausler via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 15 17:47:48 PDT 2025
https://github.com/klausler updated https://github.com/llvm/llvm-project/pull/153688
>From ae52c13d5ee393fc031314689ec5df0435691c3e Mon Sep 17 00:00:00 2001
From: Peter Klausler <pklausler at nvidia.com>
Date: Thu, 14 Aug 2025 13:43:17 -0700
Subject: [PATCH] [flang][runtime] OPEN(existingUnit,POSITION=)
Ensure that when a connected unit is reopened with POSITION='REWIND'
or 'APPEND', and a STATUS='OLD' or unspecified, that it is actually
repositioned as requested.
Fixes https://github.com/llvm/llvm-project/issues/153426.
---
flang-rt/include/flang-rt/runtime/file.h | 4 ++--
flang-rt/lib/runtime/external-unit.cpp | 14 +++++++-------
flang-rt/lib/runtime/file.cpp | 24 ++++++++++++++++--------
flang-rt/lib/runtime/unit.h | 4 ++++
4 files changed, 29 insertions(+), 17 deletions(-)
diff --git a/flang-rt/include/flang-rt/runtime/file.h b/flang-rt/include/flang-rt/runtime/file.h
index 3bba29722b3b8..6e35fe89b5341 100644
--- a/flang-rt/include/flang-rt/runtime/file.h
+++ b/flang-rt/include/flang-rt/runtime/file.h
@@ -68,7 +68,7 @@ class OpenFile {
void WaitAll(IoErrorHandler &);
// INQUIRE(POSITION=)
- Position InquirePosition() const;
+ Position InquirePosition(FileOffset offset) const;
private:
struct Pending {
@@ -80,7 +80,7 @@ class OpenFile {
void CheckOpen(const Terminator &);
bool Seek(FileOffset, IoErrorHandler &);
bool RawSeek(FileOffset);
- bool RawSeekToEnd();
+ bool SeekToEnd(IoErrorHandler &);
int PendingResult(const Terminator &, int);
void SetPosition(FileOffset pos) {
position_ = pos;
diff --git a/flang-rt/lib/runtime/external-unit.cpp b/flang-rt/lib/runtime/external-unit.cpp
index b8004d6315994..42441e59d9bb6 100644
--- a/flang-rt/lib/runtime/external-unit.cpp
+++ b/flang-rt/lib/runtime/external-unit.cpp
@@ -57,7 +57,7 @@ ExternalFileUnit *ExternalFileUnit::LookUpOrCreate(
}
ExternalFileUnit *ExternalFileUnit::LookUpOrCreateAnonymous(int unit,
- Direction dir, Fortran::common::optional<bool> isUnformatted,
+ Direction dir, common::optional<bool> isUnformatted,
IoErrorHandler &handler) {
// Make sure that the returned anonymous unit has been opened,
// not just created in the unitMap.
@@ -109,8 +109,8 @@ ExternalFileUnit &ExternalFileUnit::NewUnit(
return unit;
}
-bool ExternalFileUnit::OpenUnit(Fortran::common::optional<OpenStatus> status,
- Fortran::common::optional<Action> action, Position position,
+bool ExternalFileUnit::OpenUnit(common::optional<OpenStatus> status,
+ common::optional<Action> action, Position position,
OwningPtr<char> &&newPath, std::size_t newPathLength, Convert convert,
IoErrorHandler &handler) {
if (convert == Convert::Unknown) {
@@ -131,6 +131,7 @@ bool ExternalFileUnit::OpenUnit(Fortran::common::optional<OpenStatus> status,
if (!newPath.get() || isSamePath) {
// OPEN of existing unit, STATUS='OLD' or unspecified, not new FILE=
newPath.reset();
+ Open(status.value_or(OpenStatus::Old), action, position, handler);
return impliedClose;
}
// Otherwise, OPEN on open unit with new FILE= implies CLOSE
@@ -194,10 +195,9 @@ bool ExternalFileUnit::OpenUnit(Fortran::common::optional<OpenStatus> status,
return impliedClose;
}
-bool ExternalFileUnit::OpenAnonymousUnit(
- Fortran::common::optional<OpenStatus> status,
- Fortran::common::optional<Action> action, Position position,
- Convert convert, IoErrorHandler &handler) {
+bool ExternalFileUnit::OpenAnonymousUnit(common::optional<OpenStatus> status,
+ common::optional<Action> action, Position position, Convert convert,
+ IoErrorHandler &handler) {
// I/O to an unconnected unit reads/creates a local file, e.g. fort.7
std::size_t pathMaxLen{32};
auto path{SizedNew<char>{handler}(pathMaxLen)};
diff --git a/flang-rt/lib/runtime/file.cpp b/flang-rt/lib/runtime/file.cpp
index 16e73db488727..8255ec8691886 100644
--- a/flang-rt/lib/runtime/file.cpp
+++ b/flang-rt/lib/runtime/file.cpp
@@ -60,10 +60,16 @@ static int openfile_mkstemp(IoErrorHandler &handler) {
return fd;
}
-void OpenFile::Open(OpenStatus status, Fortran::common::optional<Action> action,
+void OpenFile::Open(OpenStatus status, common::optional<Action> action,
Position position, IoErrorHandler &handler) {
if (fd_ >= 0 &&
(status == OpenStatus::Old || status == OpenStatus::Unknown)) {
+ if (position == Position::Rewind) {
+ Seek(0, handler);
+ } else if (position == Position::Append) {
+ SeekToEnd(handler);
+ }
+ openPosition_ = position; // for INQUIRE(POSITION=)
return;
}
CloseFd(handler);
@@ -131,8 +137,8 @@ void OpenFile::Open(OpenStatus status, Fortran::common::optional<Action> action,
}
RUNTIME_CHECK(handler, action.has_value());
pending_.reset();
- if (fd_ >= 0 && position == Position::Append && !RawSeekToEnd()) {
- handler.SignalError(IostatOpenBadAppend);
+ if (fd_ >= 0 && position == Position::Append) {
+ SeekToEnd(handler);
}
isTerminal_ = fd_ >= 0 && IsATerminal(fd_);
mayRead_ = *action != Action::Write;
@@ -322,7 +328,7 @@ int OpenFile::WriteAsynchronously(FileOffset at, const char *buffer,
}
void OpenFile::Wait(int id, IoErrorHandler &handler) {
- Fortran::common::optional<int> ioStat;
+ common::optional<int> ioStat;
Pending *prev{nullptr};
for (Pending *p{pending_.get()}; p; p = (prev = p)->next.get()) {
if (p->id == id) {
@@ -353,13 +359,13 @@ void OpenFile::WaitAll(IoErrorHandler &handler) {
}
}
-Position OpenFile::InquirePosition() const {
+Position OpenFile::InquirePosition(FileOffset offset) const {
if (openPosition_) { // from OPEN statement
return *openPosition_;
} else { // unit has been repositioned since opening
- if (position_ == knownSize_.value_or(position_ + 1)) {
+ if (offset == knownSize_.value_or(offset + 1)) {
return Position::Append;
- } else if (position_ == 0 && mayPosition_) {
+ } else if (offset == 0 && mayPosition_) {
return Position::Rewind;
} else {
return Position::AsIs; // processor-dependent & no common behavior
@@ -391,7 +397,7 @@ bool OpenFile::RawSeek(FileOffset at) {
#endif
}
-bool OpenFile::RawSeekToEnd() {
+bool OpenFile::SeekToEnd(IoErrorHandler &handler) {
#ifdef _LARGEFILE64_SOURCE
std::int64_t at{::lseek64(fd_, 0, SEEK_END)};
#else
@@ -399,8 +405,10 @@ bool OpenFile::RawSeekToEnd() {
#endif
if (at >= 0) {
knownSize_ = at;
+ SetPosition(at);
return true;
} else {
+ handler.SignalError(IostatOpenBadAppend);
return false;
}
}
diff --git a/flang-rt/lib/runtime/unit.h b/flang-rt/lib/runtime/unit.h
index f266a486bb708..34b7c3972bd96 100644
--- a/flang-rt/lib/runtime/unit.h
+++ b/flang-rt/lib/runtime/unit.h
@@ -197,6 +197,10 @@ class ExternalFileUnit : public ConnectionState,
RT_API_ATTRS int GetAsynchronousId(IoErrorHandler &);
RT_API_ATTRS bool Wait(int);
+ RT_API_ATTRS Position InquirePosition() const {
+ return OpenFile::InquirePosition(
+ static_cast<FileOffset>(frameOffsetInFile_ + recordOffsetInFrame_));
+ }
private:
static RT_API_ATTRS UnitMap &CreateUnitMap();
More information about the llvm-commits
mailing list