Skip to content

Commit

Permalink
[flang][runtime] Handle unconsumed repeated list-directed input items (
Browse files Browse the repository at this point in the history
…#75400)

If list-directed input contains a repeated item ("20*123.0") that is not
fully consumed by the READ statement's data item list, the end of that
READ statement was repositioning the input to the repeated value
("123.0"), leading to later confusion. Cancel the input item repetition
during EndIoStatement() processing to prevent this misbehavior.

Fixes llvm-test-suite/Fortran/gfortran/regression/list_read_4.f90.
  • Loading branch information
klausler committed Dec 26, 2023
1 parent 7b50176 commit 9469dc3
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 7 deletions.
16 changes: 9 additions & 7 deletions flang/runtime/connection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,15 @@ SavedPosition::SavedPosition(IoStatementState &io) : io_{io} {
}

SavedPosition::~SavedPosition() {
ConnectionState &conn{io_.GetConnectionState()};
while (conn.currentRecordNumber > saved_.currentRecordNumber) {
io_.BackspaceRecord();
if (!cancelled_) {
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;
}
conn.leftTabLimit = saved_.leftTabLimit;
conn.furthestPositionInRecord = saved_.furthestPositionInRecord;
conn.positionInRecord = saved_.positionInRecord;
conn.pinnedFrame = saved_.pinnedFrame;
}
} // namespace Fortran::runtime::io
2 changes: 2 additions & 0 deletions flang/runtime/connection.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,12 @@ class SavedPosition {
public:
explicit SavedPosition(IoStatementState &);
~SavedPosition();
void Cancel() { cancelled_ = true; }

private:
IoStatementState &io_;
ConnectionState saved_;
bool cancelled_{false};
};

} // namespace Fortran::runtime::io
Expand Down
39 changes: 39 additions & 0 deletions flang/runtime/io-stmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,17 @@ InternalListIoStatementState<DIR>::InternalListIoStatementState(
: InternalIoStatementState<DIR>{d, sourceFile, sourceLine},
ioStatementState_{*this} {}

template <Direction DIR>
int InternalListIoStatementState<DIR>::EndIoStatement() {
if constexpr (DIR == Direction::Input) {
if (int status{ListDirectedStatementState<DIR>::EndIoStatement()};
status != IostatOk) {
return status;
}
}
return InternalIoStatementState<DIR>::EndIoStatement();
}

ExternalIoStatementBase::ExternalIoStatementBase(
ExternalFileUnit &unit, const char *sourceFile, int sourceLine)
: IoStatementBase{sourceFile, sourceLine}, unit_{unit} {}
Expand Down Expand Up @@ -707,6 +718,13 @@ ListDirectedStatementState<Direction::Output>::GetNextDataEdit(
return edit;
}

int ListDirectedStatementState<Direction::Input>::EndIoStatement() {
if (repeatPosition_) {
repeatPosition_->Cancel();
}
return IostatOk;
}

std::optional<DataEdit>
ListDirectedStatementState<Direction::Input>::GetNextDataEdit(
IoStatementState &io, int maxRepeat) {
Expand Down Expand Up @@ -818,6 +836,17 @@ ListDirectedStatementState<Direction::Input>::GetNextDataEdit(
return edit;
}

template <Direction DIR>
int ExternalListIoStatementState<DIR>::EndIoStatement() {
if constexpr (DIR == Direction::Input) {
if (auto status{ListDirectedStatementState<DIR>::EndIoStatement()};
status != IostatOk) {
return status;
}
}
return ExternalIoStatementState<DIR>::EndIoStatement();
}

template <Direction DIR>
bool ExternalUnformattedIoStatementState<DIR>::Receive(
char *data, std::size_t bytes, std::size_t elementBytes) {
Expand Down Expand Up @@ -910,6 +939,16 @@ bool ChildUnformattedIoStatementState<DIR>::Receive(
return this->child().parent().Receive(data, bytes, elementBytes);
}

template <Direction DIR> int ChildListIoStatementState<DIR>::EndIoStatement() {
if constexpr (DIR == Direction::Input) {
if (int status{ListDirectedStatementState<DIR>::EndIoStatement()};
status != IostatOk) {
return status;
}
}
return ChildIoStatementState<DIR>::EndIoStatement();
}

template class InternalIoStatementState<Direction::Output>;
template class InternalIoStatementState<Direction::Input>;
template class InternalFormattedIoStatementState<Direction::Output>;
Expand Down
7 changes: 7 additions & 0 deletions flang/runtime/io-stmt.h
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,7 @@ class ListDirectedStatementState<Direction::Input>
: public FormattedIoStatementState<Direction::Input> {
public:
bool inNamelistSequence() const { return inNamelistSequence_; }
int EndIoStatement();

// Skips value separators, handles repetition and null values.
// Vacant when '/' appears; present with descriptor == ListDirectedNullValue
Expand All @@ -317,6 +318,9 @@ class ListDirectedStatementState<Direction::Input>
// NAMELIST input item.
void ResetForNextNamelistItem(bool inNamelistSequence) {
remaining_ = 0;
if (repeatPosition_) {
repeatPosition_->Cancel();
}
eatComma_ = false;
realPart_ = imaginaryPart_ = false;
inNamelistSequence_ = inNamelistSequence;
Expand Down Expand Up @@ -399,6 +403,7 @@ class InternalListIoStatementState : public InternalIoStatementState<DIR>,
const Descriptor &, const char *sourceFile = nullptr, int sourceLine = 0);
IoStatementState &ioStatementState() { return ioStatementState_; }
using ListDirectedStatementState<DIR>::GetNextDataEdit;
int EndIoStatement();

private:
IoStatementState ioStatementState_; // points to *this
Expand Down Expand Up @@ -474,6 +479,7 @@ class ExternalListIoStatementState : public ExternalIoStatementState<DIR>,
public:
using ExternalIoStatementState<DIR>::ExternalIoStatementState;
using ListDirectedStatementState<DIR>::GetNextDataEdit;
int EndIoStatement();
};

template <Direction DIR>
Expand Down Expand Up @@ -532,6 +538,7 @@ class ChildListIoStatementState : public ChildIoStatementState<DIR>,
public:
using ChildIoStatementState<DIR>::ChildIoStatementState;
using ListDirectedStatementState<DIR>::GetNextDataEdit;
int EndIoStatement();
};

template <Direction DIR>
Expand Down

0 comments on commit 9469dc3

Please sign in to comment.