[flang-commits] [flang] 03c066a - [flang][runtime] Catch OPEN of connected file
Peter Klausler via flang-commits
flang-commits at lists.llvm.org
Sat Jun 4 11:11:30 PDT 2022
Author: Peter Klausler
Date: 2022-06-04T11:06:37-07:00
New Revision: 03c066ab134f02289df1b61db00294c1da579f9c
URL: https://github.com/llvm/llvm-project/commit/03c066ab134f02289df1b61db00294c1da579f9c
DIFF: https://github.com/llvm/llvm-project/commit/03c066ab134f02289df1b61db00294c1da579f9c.diff
LOG: [flang][runtime] Catch OPEN of connected file
Diagnose OPEN(FILE=f) when f is already connected by the same name to
a distinct external I/O unit.
Differential Revision: https://reviews.llvm.org/D127035
Added:
Modified:
flang/include/flang/Runtime/iostat.h
flang/runtime/file.cpp
flang/runtime/file.h
flang/runtime/io-api.cpp
flang/runtime/iostat.cpp
flang/runtime/unit-map.cpp
flang/runtime/unit-map.h
flang/runtime/unit.cpp
flang/runtime/unit.h
Removed:
################################################################################
diff --git a/flang/include/flang/Runtime/iostat.h b/flang/include/flang/Runtime/iostat.h
index c8154c1a3251..9453c12fc0a8 100644
--- a/flang/include/flang/Runtime/iostat.h
+++ b/flang/include/flang/Runtime/iostat.h
@@ -75,6 +75,8 @@ enum Iostat {
IostatBOZInputOverflow,
IostatIntegerInputOverflow,
IostatRealInputOverflow,
+ IostatOpenAlreadyConnected,
+ IostatCannotReposition,
};
const char *IostatErrorString(int);
diff --git a/flang/runtime/file.cpp b/flang/runtime/file.cpp
index 3b495c37d082..8ff972476285 100644
--- a/flang/runtime/file.cpp
+++ b/flang/runtime/file.cpp
@@ -377,7 +377,7 @@ bool OpenFile::Seek(FileOffset at, IoErrorHandler &handler) {
SetPosition(at);
return true;
} else {
- handler.SignalErrno();
+ handler.SignalError(IostatCannotReposition);
return false;
}
}
diff --git a/flang/runtime/file.h b/flang/runtime/file.h
index 3d43d57c1b96..a0712136a7f3 100644
--- a/flang/runtime/file.h
+++ b/flang/runtime/file.h
@@ -28,8 +28,8 @@ class OpenFile {
using FileOffset = std::int64_t;
const char *path() const { return path_.get(); }
- void set_path(OwningPtr<char> &&, std::size_t bytes);
std::size_t pathLength() const { return pathLength_; }
+ void set_path(OwningPtr<char> &&, std::size_t bytes);
bool mayRead() const { return mayRead_; }
bool mayWrite() const { return mayWrite_; }
bool mayPosition() const { return mayPosition_; }
diff --git a/flang/runtime/io-api.cpp b/flang/runtime/io-api.cpp
index b7060076ad11..99ff2f01ab4e 100644
--- a/flang/runtime/io-api.cpp
+++ b/flang/runtime/io-api.cpp
@@ -431,7 +431,9 @@ Cookie IONAME(BeginInquireFile)(const char *path, std::size_t pathLength,
Terminator oom{sourceFile, sourceLine};
auto trimmed{
SaveDefaultCharacter(path, TrimTrailingSpaces(path, pathLength), oom)};
- if (ExternalFileUnit * unit{ExternalFileUnit::LookUp(trimmed.get())}) {
+ if (ExternalFileUnit *
+ unit{ExternalFileUnit::LookUp(
+ trimmed.get(), std::strlen(trimmed.get()))}) {
// INQUIRE(FILE=) to a connected unit
return &unit->BeginIoStatement<InquireUnitState>(
*unit, sourceFile, sourceLine);
diff --git a/flang/runtime/iostat.cpp b/flang/runtime/iostat.cpp
index 017be1c9164e..0e6c162b54e4 100644
--- a/flang/runtime/iostat.cpp
+++ b/flang/runtime/iostat.cpp
@@ -94,6 +94,11 @@ const char *IostatErrorString(int iostat) {
return "Integer input value overflows variable";
case IostatRealInputOverflow:
return "Real or complex input value overflows type";
+ case IostatCannotReposition:
+ return "Attempt to reposition a unit which is connected to a file that can "
+ "only be processed sequentially";
+ case IostatOpenAlreadyConnected:
+ return "OPEN of file already connected to another unit";
default:
return nullptr;
}
diff --git a/flang/runtime/unit-map.cpp b/flang/runtime/unit-map.cpp
index 8754fbf6a23c..6ebda5c45f08 100644
--- a/flang/runtime/unit-map.cpp
+++ b/flang/runtime/unit-map.cpp
@@ -111,12 +111,13 @@ void UnitMap::FlushAll(IoErrorHandler &handler) {
}
}
-ExternalFileUnit *UnitMap::Find(const char *path) {
+ExternalFileUnit *UnitMap::Find(const char *path, std::size_t pathLen) {
if (path) {
// TODO: Faster data structure
for (int j{0}; j < buckets_; ++j) {
for (Chain *p{bucket_[j].get()}; p; p = p->next.get()) {
- if (p->unit.path() && std::strcmp(p->unit.path(), path) == 0) {
+ if (p->unit.path() && p->unit.pathLength() == pathLen &&
+ std::memcmp(p->unit.path(), path, pathLen) == 0) {
return &p->unit;
}
}
diff --git a/flang/runtime/unit-map.h b/flang/runtime/unit-map.h
index 9eb43ce6acd9..7211892ef66e 100644
--- a/flang/runtime/unit-map.h
+++ b/flang/runtime/unit-map.h
@@ -37,9 +37,9 @@ class UnitMap {
}
// Unit look-up by name is needed for INQUIRE(FILE="...")
- ExternalFileUnit *LookUp(const char *path) {
+ ExternalFileUnit *LookUp(const char *path, std::size_t pathLen) {
CriticalSection critical{lock_};
- return Find(path);
+ return Find(path, pathLen);
}
ExternalFileUnit &NewUnit(const Terminator &);
@@ -84,7 +84,7 @@ class UnitMap {
}
return nullptr;
}
- ExternalFileUnit *Find(const char *path);
+ ExternalFileUnit *Find(const char *path, std::size_t pathLen);
ExternalFileUnit &Create(int, const Terminator &);
diff --git a/flang/runtime/unit.cpp b/flang/runtime/unit.cpp
index 73a96b8bf3dc..1a50b7923582 100644
--- a/flang/runtime/unit.cpp
+++ b/flang/runtime/unit.cpp
@@ -73,8 +73,9 @@ ExternalFileUnit &ExternalFileUnit::LookUpOrCreateAnonymous(int unit,
return result;
}
-ExternalFileUnit *ExternalFileUnit::LookUp(const char *path) {
- return GetUnitMap().LookUp(path);
+ExternalFileUnit *ExternalFileUnit::LookUp(
+ const char *path, std::size_t pathLen) {
+ return GetUnitMap().LookUp(path, pathLen);
}
ExternalFileUnit &ExternalFileUnit::CreateNew(
@@ -124,6 +125,16 @@ void ExternalFileUnit::OpenUnit(std::optional<OpenStatus> status,
FlushOutput(handler);
Close(CloseStatus::Keep, handler);
}
+ if (newPath.get() && newPathLength > 0) {
+ if (const auto *already{
+ GetUnitMap().LookUp(newPath.get(), newPathLength)}) {
+ handler.SignalError(IostatOpenAlreadyConnected,
+ "OPEN(UNIT=%d,FILE='%.*s'): file is already connected to unit %d",
+ unitNumber_, static_cast<int>(newPathLength), newPath.get(),
+ already->unitNumber_);
+ return;
+ }
+ }
set_path(std::move(newPath), newPathLength);
Open(status.value_or(OpenStatus::Unknown), action, position, handler);
auto totalBytes{knownSize()};
diff --git a/flang/runtime/unit.h b/flang/runtime/unit.h
index 567aa740244a..e47fd5d5c3bc 100644
--- a/flang/runtime/unit.h
+++ b/flang/runtime/unit.h
@@ -50,7 +50,7 @@ class ExternalFileUnit : public ConnectionState,
int unit, const Terminator &, bool &wasExtant);
static ExternalFileUnit &LookUpOrCreateAnonymous(int unit, Direction,
std::optional<bool> isUnformatted, const Terminator &);
- static ExternalFileUnit *LookUp(const char *path);
+ static ExternalFileUnit *LookUp(const char *path, std::size_t pathLen);
static ExternalFileUnit &CreateNew(int unit, const Terminator &);
static ExternalFileUnit *LookUpForClose(int unit);
static ExternalFileUnit &NewUnit(const Terminator &, bool forChildIo);
More information about the flang-commits
mailing list