Skip to content

[flang][runtime] When OPEN implies CLOSE, disable later extant unit c… #69390

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 31, 2023

Conversation

klausler
Copy link
Contributor

…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.

@klausler klausler requested a review from vdonaldson October 17, 2023 22:22
@llvmbot llvmbot added flang:runtime flang Flang issues not falling into any other category labels Oct 17, 2023
@llvmbot
Copy link
Member

llvmbot commented Oct 17, 2023

@llvm/pr-subscribers-flang-runtime

Author: Peter Klausler (klausler)

Changes

…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.


Full diff: https://github.com/llvm/llvm-project/pull/69390.diff

3 Files Affected:

  • (modified) flang/runtime/io-stmt.cpp (+4-2)
  • (modified) flang/runtime/unit.cpp (+7-4)
  • (modified) flang/runtime/unit.h (+2-1)
diff --git a/flang/runtime/io-stmt.cpp b/flang/runtime/io-stmt.cpp
index 1d951a4157d3199..dedf1f8364ad373 100644
--- a/flang/runtime/io-stmt.cpp
+++ b/flang/runtime/io-stmt.cpp
@@ -248,8 +248,10 @@ void OpenStatementState::CompleteOperation() {
   }
   if (path_.get() || wasExtant_ ||
       (status_ && *status_ == OpenStatus::Scratch)) {
-    unit().OpenUnit(status_, action_, position_.value_or(Position::AsIs),
-        std::move(path_), pathLength_, convert_, *this);
+    if (unit().OpenUnit(status_, action_, position_.value_or(Position::AsIs),
+            std::move(path_), pathLength_, convert_, *this)) {
+      wasExtant_ = false; // existing unit was closed
+    }
   } else {
     unit().OpenAnonymousUnit(
         status_, action_, position_.value_or(Position::AsIs), convert_, *this);
diff --git a/flang/runtime/unit.cpp b/flang/runtime/unit.cpp
index 1c8432328848e0f..dec8d8032f6155e 100644
--- a/flang/runtime/unit.cpp
+++ b/flang/runtime/unit.cpp
@@ -90,7 +90,7 @@ ExternalFileUnit &ExternalFileUnit::NewUnit(
   return unit;
 }
 
-void ExternalFileUnit::OpenUnit(std::optional<OpenStatus> status,
+bool ExternalFileUnit::OpenUnit(std::optional<OpenStatus> status,
     std::optional<Action> action, Position position, OwningPtr<char> &&newPath,
     std::size_t newPathLength, Convert convert, IoErrorHandler &handler) {
   if (convert == Convert::Unknown) {
@@ -99,24 +99,26 @@ void ExternalFileUnit::OpenUnit(std::optional<OpenStatus> status,
   swapEndianness_ = convert == Convert::Swap ||
       (convert == Convert::LittleEndian && !isHostLittleEndian) ||
       (convert == Convert::BigEndian && isHostLittleEndian);
+  bool impliedClose{false};
   if (IsConnected()) {
     bool isSamePath{newPath.get() && path() && pathLength() == newPathLength &&
         std::memcmp(path(), newPath.get(), newPathLength) == 0};
     if (status && *status != OpenStatus::Old && isSamePath) {
       handler.SignalError("OPEN statement for connected unit may not have "
                           "explicit STATUS= other than 'OLD'");
-      return;
+      return impliedClose;
     }
     if (!newPath.get() || isSamePath) {
       // OPEN of existing unit, STATUS='OLD' or unspecified, not new FILE=
       newPath.reset();
-      return;
+      return impliedClose;
     }
     // Otherwise, OPEN on open unit with new FILE= implies CLOSE
     DoImpliedEndfile(handler);
     FlushOutput(handler);
     TruncateFrame(0, handler);
     Close(CloseStatus::Keep, handler);
+    impliedClose = true;
   }
   if (newPath.get() && newPathLength > 0) {
     if (const auto *already{
@@ -125,7 +127,7 @@ void ExternalFileUnit::OpenUnit(std::optional<OpenStatus> status,
           "OPEN(UNIT=%d,FILE='%.*s'): file is already connected to unit %d",
           unitNumber_, static_cast<int>(newPathLength), newPath.get(),
           already->unitNumber_);
-      return;
+      return impliedClose;
     }
   }
   set_path(std::move(newPath), newPathLength);
@@ -166,6 +168,7 @@ void ExternalFileUnit::OpenUnit(std::optional<OpenStatus> status,
       currentRecordNumber = *endfileRecordNumber;
     }
   }
+  return impliedClose;
 }
 
 void ExternalFileUnit::OpenAnonymousUnit(std::optional<OpenStatus> status,
diff --git a/flang/runtime/unit.h b/flang/runtime/unit.h
index b6007a9b1538595..1ec3013ba82b3fb 100644
--- a/flang/runtime/unit.h
+++ b/flang/runtime/unit.h
@@ -59,7 +59,8 @@ class ExternalFileUnit : public ConnectionState,
   static void CloseAll(IoErrorHandler &);
   static void FlushAll(IoErrorHandler &);
 
-  void OpenUnit(std::optional<OpenStatus>, std::optional<Action>, Position,
+  // Returns true if an existing unit was closed
+  bool OpenUnit(std::optional<OpenStatus>, std::optional<Action>, Position,
       OwningPtr<char> &&path, std::size_t pathLength, Convert,
       IoErrorHandler &);
   void OpenAnonymousUnit(std::optional<OpenStatus>, std::optional<Action>,

…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.
@klausler klausler merged commit ccc573c into llvm:main Oct 31, 2023
@klausler klausler deleted the bug1399 branch October 31, 2023 17:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
flang:runtime flang Flang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants