Skip to content

Commit 39c38c2

Browse files
committed
[flang] Fix list-directed plural repeated null values at end of record
A repeated null value at the end of an input record with a count > 1 would incorrectly advance to the next record when resumed. Fix. Improve some poor naming and code flow noticed while debugging, so next time will be easier. Extend a unit test to check this case. Differential Revision: https://reviews.llvm.org/D107917
1 parent 101b3fe commit 39c38c2

File tree

3 files changed

+27
-33
lines changed

3 files changed

+27
-33
lines changed

flang/runtime/io-stmt.cpp

Lines changed: 17 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -653,13 +653,13 @@ ListDirectedStatementState<Direction::Input>::GetNextDataEdit(
653653
comma = ';';
654654
}
655655
if (remaining_ > 0 && !realPart_) { // "r*c" repetition in progress
656-
while (connection.currentRecordNumber > initialRecordNumber_) {
656+
while (connection.currentRecordNumber > repeatRecordNumber_) {
657657
io.BackspaceRecord();
658658
}
659-
connection.HandleAbsolutePosition(initialPositionInRecord_);
659+
connection.HandleAbsolutePosition(repeatPositionInRecord_);
660660
if (!imaginaryPart_) {
661661
edit.repeat = std::min<int>(remaining_, maxRepeat);
662-
auto ch{io.GetNextNonBlank()};
662+
auto ch{io.GetCurrentChar()};
663663
if (!ch || *ch == ' ' || *ch == '\t' || *ch == comma) {
664664
// "r*" repeated null
665665
edit.descriptor = DataEdit::ListDirectedNullValue;
@@ -669,14 +669,22 @@ ListDirectedStatementState<Direction::Input>::GetNextDataEdit(
669669
return edit;
670670
}
671671
// Skip separators, handle a "r*c" repeat count; see 13.10.2 in Fortran 2018
672-
auto ch{io.GetNextNonBlank()};
673672
if (imaginaryPart_) {
674673
imaginaryPart_ = false;
675674
} else if (realPart_) {
676675
realPart_ = false;
677676
imaginaryPart_ = true;
678677
edit.descriptor = DataEdit::ListDirectedImaginaryPart;
679678
}
679+
auto ch{io.GetNextNonBlank()};
680+
if (ch && *ch == comma && eatComma_) {
681+
// Consume comma & whitespace after previous item.
682+
// This includes the comma between real and imaginary components
683+
// in list-directed/NAMELIST complex input.
684+
io.HandleRelativePosition(1);
685+
ch = io.GetNextNonBlank();
686+
}
687+
eatComma_ = true;
680688
if (!ch) {
681689
return std::nullopt;
682690
}
@@ -685,25 +693,9 @@ ListDirectedStatementState<Direction::Input>::GetNextDataEdit(
685693
edit.descriptor = DataEdit::ListDirectedNullValue;
686694
return edit;
687695
}
688-
bool isFirstItem{isFirstItem_};
689-
isFirstItem_ = false;
690-
if (*ch == comma) {
691-
if (isFirstItem) {
692-
edit.descriptor = DataEdit::ListDirectedNullValue;
693-
return edit;
694-
}
695-
// Consume comma & whitespace after previous item.
696-
// This includes the comma between real and imaginary components
697-
// in list-directed/NAMELIST complex input.
698-
io.HandleRelativePosition(1);
699-
ch = io.GetNextNonBlank();
700-
if (!ch) {
701-
return std::nullopt;
702-
}
703-
if (*ch == comma || *ch == '/') {
704-
edit.descriptor = DataEdit::ListDirectedNullValue;
705-
return edit;
706-
}
696+
if (*ch == comma) { // separator: null value
697+
edit.descriptor = DataEdit::ListDirectedNullValue;
698+
return edit;
707699
}
708700
if (imaginaryPart_) { // can't repeat components
709701
return edit;
@@ -734,8 +726,8 @@ ListDirectedStatementState<Direction::Input>::GetNextDataEdit(
734726
}
735727
edit.repeat = std::min<int>(r, maxRepeat);
736728
remaining_ = r - edit.repeat;
737-
initialRecordNumber_ = connection.currentRecordNumber;
738-
initialPositionInRecord_ = connection.positionInRecord;
729+
repeatRecordNumber_ = connection.currentRecordNumber;
730+
repeatPositionInRecord_ = connection.positionInRecord;
739731
} else { // not a repetition count, just an integer value; rewind
740732
connection.positionInRecord = start;
741733
}

flang/runtime/io-stmt.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -223,15 +223,15 @@ class ListDirectedStatementState<Direction::Input>
223223
// successive NAMELIST input item.
224224
void ResetForNextNamelistItem() {
225225
remaining_ = 0;
226-
isFirstItem_ = true;
226+
eatComma_ = false;
227227
realPart_ = imaginaryPart_ = false;
228228
}
229229

230230
private:
231231
int remaining_{0}; // for "r*" repetition
232-
std::int64_t initialRecordNumber_;
233-
std::int64_t initialPositionInRecord_;
234-
bool isFirstItem_{true}; // leading separator implies null first item
232+
std::int64_t repeatRecordNumber_;
233+
std::int64_t repeatPositionInRecord_;
234+
bool eatComma_{false}; // consume comma after previously read item
235235
bool hitSlash_{false}; // once '/' is seen, nullify further items
236236
bool realPart_{false};
237237
bool imaginaryPart_{false};

flang/unittests/Runtime/ListInputTest.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ TEST(InputTest, TestListInputIntegerList) {
7373
char buffer[numBuffers][maxBufferLength];
7474
int j{0};
7575
SetCharacter(buffer[j++], maxBufferLength, "1 2 2*3 ,");
76-
SetCharacter(buffer[j++], maxBufferLength, ",6,,8,1*");
76+
SetCharacter(buffer[j++], maxBufferLength, ",6,,8,2*");
7777

7878
StaticDescriptor<1> staticDescriptor;
7979
Descriptor &whole{staticDescriptor.descriptor()};
@@ -83,13 +83,15 @@ TEST(InputTest, TestListInputIntegerList) {
8383
whole.Check();
8484
auto *cookie{IONAME(BeginInternalArrayListInput)(whole)};
8585

86-
constexpr int listInputLength{9};
86+
constexpr int listInputLength{10};
8787

8888
// Negative numbers will be overwritten by _expectedOutput_, and positive
8989
// numbers will not be as their indices are "Null values" of the Fortran 2018
9090
// standard 13.10.3.2 in the format strings _buffer_
91-
std::int64_t actualOutput[listInputLength]{-1, -2, -3, -4, 5, -6, 7, -8, 9};
92-
const std::int64_t expectedOutput[listInputLength]{1, 2, 3, 3, 5, 6, 7, 8, 9};
91+
std::int64_t actualOutput[listInputLength]{
92+
-1, -2, -3, -4, 5, -6, 7, -8, 9, 10};
93+
const std::int64_t expectedOutput[listInputLength]{
94+
1, 2, 3, 3, 5, 6, 7, 8, 9, 10};
9395
for (j = 0; j < listInputLength; ++j) {
9496
IONAME(InputInteger)(cookie, actualOutput[j]);
9597
}

0 commit comments

Comments
 (0)