[flang-commits] [flang] e782360 - [flang] Complete the fix for NAMELIST look-ahead case
Peter Klausler via flang-commits
flang-commits at lists.llvm.org
Mon Nov 8 10:01:30 PST 2021
Author: Peter Klausler
Date: 2021-11-08T10:01:16-08:00
New Revision: e7823608bc8e63f409ecd262b0e4a5a65a2ca9f8
URL: https://github.com/llvm/llvm-project/commit/e7823608bc8e63f409ecd262b0e4a5a65a2ca9f8
DIFF: https://github.com/llvm/llvm-project/commit/e7823608bc8e63f409ecd262b0e4a5a65a2ca9f8.diff
LOG: [flang] Complete the fix for NAMELIST look-ahead case
When processing the devious NAMELIST input
&group logarray = t t t
= 666 /
for LOGICAL::logarray(3) and INTEGER::t, the runtime library
needs to do some look-ahead on the input stream to make sure
that the last "t" on the first line is a truth value rather than
an item name -- which in this case it is. This look-ahead
was implemented in a previous patch but only worked for internal
input cases; this patch implements look-ahead capabilities for
input from an external file, too (and also adjusts repeated
list-directed input items to use this infrastructure, too).
Differential Revision: https://reviews.llvm.org/D113311
Added:
Modified:
flang/runtime/connection.cpp
flang/runtime/connection.h
flang/runtime/io-stmt.cpp
flang/runtime/io-stmt.h
flang/runtime/namelist.cpp
flang/runtime/unit.cpp
Removed:
################################################################################
diff --git a/flang/runtime/connection.cpp b/flang/runtime/connection.cpp
index 29d3220f43fc..765ce90520c2 100644
--- a/flang/runtime/connection.cpp
+++ b/flang/runtime/connection.cpp
@@ -8,6 +8,7 @@
#include "connection.h"
#include "environment.h"
+#include "io-stmt.h"
#include <algorithm>
namespace Fortran::runtime::io {
@@ -33,4 +34,21 @@ void ConnectionState::HandleAbsolutePosition(std::int64_t n) {
void ConnectionState::HandleRelativePosition(std::int64_t n) {
positionInRecord = std::max(leftTabLimit.value_or(0), positionInRecord + n);
}
+
+SavedPosition::SavedPosition(IoStatementState &io) : io_{io} {
+ ConnectionState &conn{io_.GetConnectionState()};
+ saved_ = conn;
+ conn.pinnedFrame = true;
+}
+
+SavedPosition::~SavedPosition() {
+ ConnectionState &conn{io_.GetConnectionState()};
+ while (conn.currentRecordNumber > saved_.currentRecordNumber) {
+ io_.BackspaceRecord();
+ }
+ conn.leftTabLimit = saved_.leftTabLimit;
+ conn.furthestPositionInRecord = saved_.furthestPositionInRecord;
+ conn.positionInRecord = saved_.positionInRecord;
+ conn.pinnedFrame = saved_.pinnedFrame;
+}
} // namespace Fortran::runtime::io
diff --git a/flang/runtime/connection.h b/flang/runtime/connection.h
index dfeebeb522dc..0eb2038500b2 100644
--- a/flang/runtime/connection.h
+++ b/flang/runtime/connection.h
@@ -17,6 +17,8 @@
namespace Fortran::runtime::io {
+class IoStatementState;
+
enum class Direction { Output, Input };
enum class Access { Sequential, Direct, Stream };
@@ -57,40 +59,25 @@ struct ConnectionState : public ConnectionAttributes {
// or an end-of-file READ condition on a sequential access file
std::optional<std::int64_t> endfileRecordNumber;
+ // Mutable modes set at OPEN() that can be overridden in READ/WRITE & FORMAT
+ MutableModes modes; // BLANK=, DECIMAL=, SIGN=, ROUND=, PAD=, DELIM=, kP
+
// Set when processing repeated items during list-directed & NAMELIST input
// in order to keep a span of records in frame on a non-positionable file,
// so that backspacing to the beginning of the repeated item doesn't require
// repositioning the external storage medium when that's impossible.
- std::optional<std::int64_t> resumptionRecordNumber;
-
- // Mutable modes set at OPEN() that can be overridden in READ/WRITE & FORMAT
- MutableModes modes; // BLANK=, DECIMAL=, SIGN=, ROUND=, PAD=, DELIM=, kP
+ bool pinnedFrame{false};
};
// Utility class for capturing and restoring a position in an input stream.
class SavedPosition {
public:
- explicit SavedPosition(ConnectionState &c)
- : connection_{c}, positionInRecord_{c.positionInRecord},
- furthestPositionInRecord_{c.furthestPositionInRecord},
- leftTabLimit_{c.leftTabLimit}, previousResumptionRecordNumber_{
- c.resumptionRecordNumber} {
- c.resumptionRecordNumber = c.currentRecordNumber;
- }
- ~SavedPosition() {
- connection_.currentRecordNumber = *connection_.resumptionRecordNumber;
- connection_.resumptionRecordNumber = previousResumptionRecordNumber_;
- connection_.leftTabLimit = leftTabLimit_;
- connection_.furthestPositionInRecord = furthestPositionInRecord_;
- connection_.positionInRecord = positionInRecord_;
- }
+ explicit SavedPosition(IoStatementState &);
+ ~SavedPosition();
private:
- ConnectionState &connection_;
- std::int64_t positionInRecord_;
- std::int64_t furthestPositionInRecord_;
- std::optional<std::int64_t> leftTabLimit_;
- std::optional<std::int64_t> previousResumptionRecordNumber_;
+ IoStatementState &io_;
+ ConnectionState saved_;
};
} // namespace Fortran::runtime::io
diff --git a/flang/runtime/io-stmt.cpp b/flang/runtime/io-stmt.cpp
index 44fc7aefea6e..784d14496aac 100644
--- a/flang/runtime/io-stmt.cpp
+++ b/flang/runtime/io-stmt.cpp
@@ -680,14 +680,8 @@ ListDirectedStatementState<Direction::Input>::GetNextDataEdit(
comma = ';';
}
if (remaining_ > 0 && !realPart_) { // "r*c" repetition in progress
- RUNTIME_CHECK(
- io.GetIoErrorHandler(), connection.resumptionRecordNumber.has_value());
- while (connection.currentRecordNumber >
- connection.resumptionRecordNumber.value_or(
- connection.currentRecordNumber)) {
- io.BackspaceRecord();
- }
- connection.HandleAbsolutePosition(repeatPositionInRecord_);
+ RUNTIME_CHECK(io.GetIoErrorHandler(), repeatPosition_.has_value());
+ repeatPosition_.reset(); // restores the saved position
if (!imaginaryPart_) {
edit.repeat = std::min<int>(remaining_, maxRepeat);
auto ch{io.GetCurrentChar()};
@@ -697,8 +691,8 @@ ListDirectedStatementState<Direction::Input>::GetNextDataEdit(
}
}
remaining_ -= edit.repeat;
- if (remaining_ <= 0) {
- connection.resumptionRecordNumber.reset();
+ if (remaining_ > 0) {
+ repeatPosition_.emplace(io);
}
return edit;
}
@@ -761,11 +755,8 @@ ListDirectedStatementState<Direction::Input>::GetNextDataEdit(
edit.repeat = std::min<int>(r, maxRepeat);
remaining_ = r - edit.repeat;
if (remaining_ > 0) {
- connection.resumptionRecordNumber = connection.currentRecordNumber;
- } else {
- connection.resumptionRecordNumber.reset();
+ repeatPosition_.emplace(io);
}
- repeatPositionInRecord_ = connection.positionInRecord;
} else { // not a repetition count, just an integer value; rewind
connection.positionInRecord = start;
}
diff --git a/flang/runtime/io-stmt.h b/flang/runtime/io-stmt.h
index 7e683b146eb1..0006cab2b2ae 100644
--- a/flang/runtime/io-stmt.h
+++ b/flang/runtime/io-stmt.h
@@ -241,7 +241,7 @@ class ListDirectedStatementState<Direction::Input>
private:
int remaining_{0}; // for "r*" repetition
- std::int64_t repeatPositionInRecord_;
+ std::optional<SavedPosition> repeatPosition_;
bool eatComma_{false}; // consume comma after previously read item
bool hitSlash_{false}; // once '/' is seen, nullify further items
bool realPart_{false};
diff --git a/flang/runtime/namelist.cpp b/flang/runtime/namelist.cpp
index 03fddd61f24d..11fe49b5fc9a 100644
--- a/flang/runtime/namelist.cpp
+++ b/flang/runtime/namelist.cpp
@@ -359,7 +359,7 @@ bool IsNamelistName(IoStatementState &io) {
if (io.get_if<ListDirectedStatementState<Direction::Input>>()) {
ConnectionState &connection{io.GetConnectionState()};
if (connection.modes.inNamelist) {
- SavedPosition savedPosition{connection};
+ SavedPosition savedPosition{io};
if (auto ch{io.GetNextNonBlank()}) {
if (IsLegalIdStart(*ch)) {
do {
@@ -368,7 +368,7 @@ bool IsNamelistName(IoStatementState &io) {
} while (ch && IsLegalIdChar(*ch));
ch = io.GetNextNonBlank();
// TODO: how to deal with NaN(...) ambiguity?
- return ch && (ch == '=' || ch == '(' || ch == '%');
+ return ch && (*ch == '=' || *ch == '(' || *ch == '%');
}
}
}
diff --git a/flang/runtime/unit.cpp b/flang/runtime/unit.cpp
index 575af15513d7..829b471f3424 100644
--- a/flang/runtime/unit.cpp
+++ b/flang/runtime/unit.cpp
@@ -406,30 +406,30 @@ void ExternalFileUnit::FinishReadingRecord(IoErrorHandler &handler) {
// avoid bogus crashes in END/ERR circumstances
} else if (access == Access::Sequential) {
RUNTIME_CHECK(handler, recordLength.has_value());
+ recordOffsetInFrame_ += *recordLength;
if (isFixedRecordLength && access == Access::Direct) {
- frameOffsetInFile_ += recordOffsetInFrame_ + *recordLength;
+ frameOffsetInFile_ += recordOffsetInFrame_;
recordOffsetInFrame_ = 0;
} else {
RUNTIME_CHECK(handler, isUnformatted.has_value());
+ recordLength.reset();
if (isUnformatted.value_or(false)) {
// Retain footer in frame for more efficient BACKSPACE
- frameOffsetInFile_ += recordOffsetInFrame_ + *recordLength;
+ frameOffsetInFile_ += recordOffsetInFrame_;
recordOffsetInFrame_ = sizeof(std::uint32_t);
- recordLength.reset();
} else { // formatted
- if (FrameLength() > recordOffsetInFrame_ + *recordLength &&
- Frame()[recordOffsetInFrame_ + *recordLength] == '\r') {
+ if (FrameLength() > recordOffsetInFrame_ &&
+ Frame()[recordOffsetInFrame_] == '\r') {
++recordOffsetInFrame_;
}
if (FrameLength() >= recordOffsetInFrame_ &&
- Frame()[recordOffsetInFrame_ + *recordLength] == '\n') {
+ Frame()[recordOffsetInFrame_] == '\n') {
++recordOffsetInFrame_;
}
- if (!resumptionRecordNumber || mayPosition()) {
- frameOffsetInFile_ += recordOffsetInFrame_ + *recordLength;
+ if (!pinnedFrame || mayPosition()) {
+ frameOffsetInFile_ += recordOffsetInFrame_;
recordOffsetInFrame_ = 0;
}
- recordLength.reset();
}
}
}
More information about the flang-commits
mailing list