diff options
author | Peter Klausler <pklausler@nvidia.com> | 2023-07-18 17:05:47 -0700 |
---|---|---|
committer | Peter Klausler <pklausler@nvidia.com> | 2023-07-21 13:13:08 -0700 |
commit | afdbf1b731ef582008e9ad08ecf787b2b6c2dd88 (patch) | |
tree | 13730fbce4544cc27f3ecc42be9e92a5a717be18 /flang | |
parent | 25d34215bb80459dd328d6f8eb86c43684375d88 (diff) | |
download | llvm-afdbf1b731ef582008e9ad08ecf787b2b6c2dd88.zip llvm-afdbf1b731ef582008e9ad08ecf787b2b6c2dd88.tar.gz llvm-afdbf1b731ef582008e9ad08ecf787b2b6c2dd88.tar.bz2 |
[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
Diffstat (limited to 'flang')
-rw-r--r-- | flang/include/flang/Runtime/iostat.h | 1 | ||||
-rw-r--r-- | flang/runtime/io-api.cpp | 9 | ||||
-rw-r--r-- | flang/runtime/io-stmt.cpp | 6 | ||||
-rw-r--r-- | flang/runtime/io-stmt.h | 7 | ||||
-rw-r--r-- | flang/runtime/iostat.cpp | 2 |
5 files changed, 18 insertions, 7 deletions
diff --git a/flang/include/flang/Runtime/iostat.h b/flang/include/flang/Runtime/iostat.h index ddb82ce..faadaab 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 fe58bbc..2c17f10 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 d18f81b..4be7e61 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 33653e6..fa432d0 100644 --- a/flang/runtime/io-stmt.h +++ b/flang/runtime/io-stmt.h @@ -537,10 +537,10 @@ public: // 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 @@ public: 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 f34bde2..d786e50 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; } |