Skip to content

Commit 9469dc3

Browse files
authored
[flang][runtime] Handle unconsumed repeated list-directed input items (llvm#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.
1 parent 7b50176 commit 9469dc3

File tree

4 files changed

+57
-7
lines changed

4 files changed

+57
-7
lines changed

flang/runtime/connection.cpp

+9-7
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,15 @@ SavedPosition::SavedPosition(IoStatementState &io) : io_{io} {
4646
}
4747

4848
SavedPosition::~SavedPosition() {
49-
ConnectionState &conn{io_.GetConnectionState()};
50-
while (conn.currentRecordNumber > saved_.currentRecordNumber) {
51-
io_.BackspaceRecord();
49+
if (!cancelled_) {
50+
ConnectionState &conn{io_.GetConnectionState()};
51+
while (conn.currentRecordNumber > saved_.currentRecordNumber) {
52+
io_.BackspaceRecord();
53+
}
54+
conn.leftTabLimit = saved_.leftTabLimit;
55+
conn.furthestPositionInRecord = saved_.furthestPositionInRecord;
56+
conn.positionInRecord = saved_.positionInRecord;
57+
conn.pinnedFrame = saved_.pinnedFrame;
5258
}
53-
conn.leftTabLimit = saved_.leftTabLimit;
54-
conn.furthestPositionInRecord = saved_.furthestPositionInRecord;
55-
conn.positionInRecord = saved_.positionInRecord;
56-
conn.pinnedFrame = saved_.pinnedFrame;
5759
}
5860
} // namespace Fortran::runtime::io

flang/runtime/connection.h

+2
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,12 @@ class SavedPosition {
111111
public:
112112
explicit SavedPosition(IoStatementState &);
113113
~SavedPosition();
114+
void Cancel() { cancelled_ = true; }
114115

115116
private:
116117
IoStatementState &io_;
117118
ConnectionState saved_;
119+
bool cancelled_{false};
118120
};
119121

120122
} // namespace Fortran::runtime::io

flang/runtime/io-stmt.cpp

+39
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,17 @@ InternalListIoStatementState<DIR>::InternalListIoStatementState(
189189
: InternalIoStatementState<DIR>{d, sourceFile, sourceLine},
190190
ioStatementState_{*this} {}
191191

192+
template <Direction DIR>
193+
int InternalListIoStatementState<DIR>::EndIoStatement() {
194+
if constexpr (DIR == Direction::Input) {
195+
if (int status{ListDirectedStatementState<DIR>::EndIoStatement()};
196+
status != IostatOk) {
197+
return status;
198+
}
199+
}
200+
return InternalIoStatementState<DIR>::EndIoStatement();
201+
}
202+
192203
ExternalIoStatementBase::ExternalIoStatementBase(
193204
ExternalFileUnit &unit, const char *sourceFile, int sourceLine)
194205
: IoStatementBase{sourceFile, sourceLine}, unit_{unit} {}
@@ -707,6 +718,13 @@ ListDirectedStatementState<Direction::Output>::GetNextDataEdit(
707718
return edit;
708719
}
709720

721+
int ListDirectedStatementState<Direction::Input>::EndIoStatement() {
722+
if (repeatPosition_) {
723+
repeatPosition_->Cancel();
724+
}
725+
return IostatOk;
726+
}
727+
710728
std::optional<DataEdit>
711729
ListDirectedStatementState<Direction::Input>::GetNextDataEdit(
712730
IoStatementState &io, int maxRepeat) {
@@ -818,6 +836,17 @@ ListDirectedStatementState<Direction::Input>::GetNextDataEdit(
818836
return edit;
819837
}
820838

839+
template <Direction DIR>
840+
int ExternalListIoStatementState<DIR>::EndIoStatement() {
841+
if constexpr (DIR == Direction::Input) {
842+
if (auto status{ListDirectedStatementState<DIR>::EndIoStatement()};
843+
status != IostatOk) {
844+
return status;
845+
}
846+
}
847+
return ExternalIoStatementState<DIR>::EndIoStatement();
848+
}
849+
821850
template <Direction DIR>
822851
bool ExternalUnformattedIoStatementState<DIR>::Receive(
823852
char *data, std::size_t bytes, std::size_t elementBytes) {
@@ -910,6 +939,16 @@ bool ChildUnformattedIoStatementState<DIR>::Receive(
910939
return this->child().parent().Receive(data, bytes, elementBytes);
911940
}
912941

942+
template <Direction DIR> int ChildListIoStatementState<DIR>::EndIoStatement() {
943+
if constexpr (DIR == Direction::Input) {
944+
if (int status{ListDirectedStatementState<DIR>::EndIoStatement()};
945+
status != IostatOk) {
946+
return status;
947+
}
948+
}
949+
return ChildIoStatementState<DIR>::EndIoStatement();
950+
}
951+
913952
template class InternalIoStatementState<Direction::Output>;
914953
template class InternalIoStatementState<Direction::Input>;
915954
template class InternalFormattedIoStatementState<Direction::Output>;

flang/runtime/io-stmt.h

+7
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,7 @@ class ListDirectedStatementState<Direction::Input>
304304
: public FormattedIoStatementState<Direction::Input> {
305305
public:
306306
bool inNamelistSequence() const { return inNamelistSequence_; }
307+
int EndIoStatement();
307308

308309
// Skips value separators, handles repetition and null values.
309310
// Vacant when '/' appears; present with descriptor == ListDirectedNullValue
@@ -317,6 +318,9 @@ class ListDirectedStatementState<Direction::Input>
317318
// NAMELIST input item.
318319
void ResetForNextNamelistItem(bool inNamelistSequence) {
319320
remaining_ = 0;
321+
if (repeatPosition_) {
322+
repeatPosition_->Cancel();
323+
}
320324
eatComma_ = false;
321325
realPart_ = imaginaryPart_ = false;
322326
inNamelistSequence_ = inNamelistSequence;
@@ -399,6 +403,7 @@ class InternalListIoStatementState : public InternalIoStatementState<DIR>,
399403
const Descriptor &, const char *sourceFile = nullptr, int sourceLine = 0);
400404
IoStatementState &ioStatementState() { return ioStatementState_; }
401405
using ListDirectedStatementState<DIR>::GetNextDataEdit;
406+
int EndIoStatement();
402407

403408
private:
404409
IoStatementState ioStatementState_; // points to *this
@@ -474,6 +479,7 @@ class ExternalListIoStatementState : public ExternalIoStatementState<DIR>,
474479
public:
475480
using ExternalIoStatementState<DIR>::ExternalIoStatementState;
476481
using ListDirectedStatementState<DIR>::GetNextDataEdit;
482+
int EndIoStatement();
477483
};
478484

479485
template <Direction DIR>
@@ -532,6 +538,7 @@ class ChildListIoStatementState : public ChildIoStatementState<DIR>,
532538
public:
533539
using ChildIoStatementState<DIR>::ChildIoStatementState;
534540
using ListDirectedStatementState<DIR>::GetNextDataEdit;
541+
int EndIoStatement();
535542
};
536543

537544
template <Direction DIR>

0 commit comments

Comments
 (0)