[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