[flang-commits] [flang] afdbf1b - [flang][runtime] Detect NEWUNIT= without FILE= or STATUS='SCRATCH'

Peter Klausler via flang-commits flang-commits at lists.llvm.org
Fri Jul 21 13:13:34 PDT 2023


Author: Peter Klausler
Date: 2023-07-21T13:13:08-07:00
New Revision: afdbf1b731ef582008e9ad08ecf787b2b6c2dd88

URL: https://github.com/llvm/llvm-project/commit/afdbf1b731ef582008e9ad08ecf787b2b6c2dd88
DIFF: https://github.com/llvm/llvm-project/commit/afdbf1b731ef582008e9ad08ecf787b2b6c2dd88.diff

LOG: [flang][runtime] Detect NEWUNIT= without FILE= or STATUS='SCRATCH'

It is an error to open a new unit with OPEN(NEWUNIT=) and have
neither a file name nor a scratch status.  Catch it, and report a
new error code.

Differential Revision: https://reviews.llvm.org/D155967

Added: 
    

Modified: 
    flang/include/flang/Runtime/iostat.h
    flang/runtime/io-api.cpp
    flang/runtime/io-stmt.cpp
    flang/runtime/io-stmt.h
    flang/runtime/iostat.cpp

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Runtime/iostat.h b/flang/include/flang/Runtime/iostat.h
index ddb82ce0ca2386..faadaab8e90ffa 100644
--- a/flang/include/flang/Runtime/iostat.h
+++ b/flang/include/flang/Runtime/iostat.h
@@ -83,6 +83,7 @@ enum Iostat {
   IostatBadUnitNumber,
   IostatBadFlushUnit,
   IostatBadOpOnChildUnit,
+  IostatBadNewUnit,
 };
 
 const char *IostatErrorString(int);

diff  --git a/flang/runtime/io-api.cpp b/flang/runtime/io-api.cpp
index fe58bbc75f8323..2c17f10e77693b 100644
--- a/flang/runtime/io-api.cpp
+++ b/flang/runtime/io-api.cpp
@@ -379,8 +379,8 @@ Cookie IONAME(BeginOpenUnit)( // OPEN(without NEWUNIT=)
           IostatBadOpOnChildUnit, nullptr /* no unit */, sourceFile,
           sourceLine);
     } else {
-      return &unit->BeginIoStatement<OpenStatementState>(
-          terminator, *unit, wasExtant, sourceFile, sourceLine);
+      return &unit->BeginIoStatement<OpenStatementState>(terminator, *unit,
+          wasExtant, false /*not NEWUNIT=*/, sourceFile, sourceLine);
     }
   } else {
     return NoopUnit(terminator, unitNumber, IostatBadUnitNumber);
@@ -392,8 +392,9 @@ Cookie IONAME(BeginOpenNewUnit)( // OPEN(NEWUNIT=j)
   Terminator terminator{sourceFile, sourceLine};
   ExternalFileUnit &unit{
       ExternalFileUnit::NewUnit(terminator, false /*not child I/O*/)};
-  return &unit.BeginIoStatement<OpenStatementState>(
-      terminator, unit, false /*was an existing file*/, sourceFile, sourceLine);
+  return &unit.BeginIoStatement<OpenStatementState>(terminator, unit,
+      false /*was an existing file*/, true /*NEWUNIT=*/, sourceFile,
+      sourceLine);
 }
 
 Cookie IONAME(BeginWait)(ExternalUnit unitNumber, AsynchronousId id,

diff  --git a/flang/runtime/io-stmt.cpp b/flang/runtime/io-stmt.cpp
index d18f81b93faf24..4be7e6135c04f0 100644
--- a/flang/runtime/io-stmt.cpp
+++ b/flang/runtime/io-stmt.cpp
@@ -240,6 +240,12 @@ void OpenStatementState::CompleteOperation() {
       SignalError("FILE= may not appear on OPEN with STATUS='SCRATCH'");
     }
   }
+  // F'2023 12.5.6.13 - NEWUNIT= requires either FILE= or STATUS='SCRATCH'
+  if (isNewUnit_ && !path_.get() &&
+      status_.value_or(OpenStatus::Unknown) != OpenStatus::Scratch) {
+    SignalError(IostatBadNewUnit);
+    status_ = OpenStatus::Scratch; // error recovery
+  }
   if (path_.get() || wasExtant_ ||
       (status_ && *status_ == OpenStatus::Scratch)) {
     unit().OpenUnit(status_, action_, position_.value_or(Position::AsIs),

diff  --git a/flang/runtime/io-stmt.h b/flang/runtime/io-stmt.h
index 33653e69ad4ed6..fa432d07a680de 100644
--- a/flang/runtime/io-stmt.h
+++ b/flang/runtime/io-stmt.h
@@ -537,10 +537,10 @@ class ChildUnformattedIoStatementState : public ChildIoStatementState<DIR> {
 // OPEN
 class OpenStatementState : public ExternalIoStatementBase {
 public:
-  OpenStatementState(ExternalFileUnit &unit, bool wasExtant,
+  OpenStatementState(ExternalFileUnit &unit, bool wasExtant, bool isNewUnit,
       const char *sourceFile = nullptr, int sourceLine = 0)
-      : ExternalIoStatementBase{unit, sourceFile, sourceLine}, wasExtant_{
-                                                                   wasExtant} {}
+      : ExternalIoStatementBase{unit, sourceFile, sourceLine},
+        wasExtant_{wasExtant}, isNewUnit_{isNewUnit} {}
   bool wasExtant() const { return wasExtant_; }
   void set_status(OpenStatus status) { status_ = status; } // STATUS=
   void set_path(const char *, std::size_t); // FILE=
@@ -555,6 +555,7 @@ class OpenStatementState : public ExternalIoStatementBase {
 
 private:
   bool wasExtant_;
+  bool isNewUnit_;
   std::optional<OpenStatus> status_;
   std::optional<Position> position_;
   std::optional<Action> action_;

diff  --git a/flang/runtime/iostat.cpp b/flang/runtime/iostat.cpp
index f34bde28be9d06..d786e505433f8e 100644
--- a/flang/runtime/iostat.cpp
+++ b/flang/runtime/iostat.cpp
@@ -111,6 +111,8 @@ const char *IostatErrorString(int iostat) {
     return "FLUSH attempted on a bad or unconnected unit number";
   case IostatBadOpOnChildUnit:
     return "Impermissible I/O statement on child I/O unit";
+  case IostatBadNewUnit:
+    return "NEWUNIT= without FILE= or STATUS='SCRATCH'";
   default:
     return nullptr;
   }


        


More information about the flang-commits mailing list