[flang][runtime] Allow some list-directed child output to advance (#166847)

List-directed child input is allowed to advance to new records in some
circumstances, and list-directed output should be as well so that e.g.
NAMELIST output via a defined WRITE(FORMATTED) generic doesn't get
truncated by FORT_FMT_RECL.

Fixes https://github.com/llvm/llvm-project/issues/166804.
This commit is contained in:
Peter Klausler
2025-11-07 08:42:04 -08:00
committed by GitHub
parent 3d0ae1e78a
commit 1baf7dbed2
3 changed files with 19 additions and 19 deletions

View File

@@ -730,8 +730,7 @@ public:
RT_API_ATTRS bool AdvanceRecord(int = 1);
RT_API_ATTRS int EndIoStatement();
RT_API_ATTRS bool CanAdvance() {
return DIR == Direction::Input &&
(canAdvance_ || this->mutableModes().inNamelist);
return canAdvance_ || this->mutableModes().inNamelist;
}
private:

View File

@@ -175,9 +175,10 @@ bool RT_API_ATTRS EditIntegerOutput(IoStatementState &io, const DataEdit &edit,
}
if (edit.IsListDirected()) {
int total{std::max(leadingSpaces, 1) + subTotal};
if (io.GetConnectionState().NeedAdvance(static_cast<std::size_t>(total)) &&
!io.AdvanceRecord()) {
return false;
if (io.GetConnectionState().NeedAdvance(static_cast<std::size_t>(total))) {
if (!io.AdvanceRecord()) {
return false;
}
}
leadingSpaces = 1;
} else if (!edit.width) {

View File

@@ -1109,20 +1109,20 @@ ChildListIoStatementState<DIR>::ChildListIoStatementState(
ChildIo &child, const char *sourceFile, int sourceLine)
: ChildIoStatementState<DIR>{child, sourceFile, sourceLine} {
#if !defined(RT_DEVICE_AVOID_RECURSION)
if constexpr (DIR == Direction::Input) {
if (const auto *listInput{child.parent()
.get_if<ListDirectedStatementState<Direction::Input>>()}) {
this->set_eatComma(listInput->eatComma());
this->namelistGroup_ = listInput->namelistGroup();
if (auto *childListInput{child.parent()
.get_if<ChildListIoStatementState<Direction::Input>>()}) {
// Child list input whose parent is child list input: can advance
// if the parent can.
this->canAdvance_ = childListInput->CanAdvance();
} else {
// Child list input of top-level list input: can advance.
this->canAdvance_ = true;
}
if (const auto *listParent{
child.parent().get_if<ListDirectedStatementState<DIR>>()}) {
if constexpr (DIR == Direction::Input) {
this->set_eatComma(listParent->eatComma());
this->namelistGroup_ = listParent->namelistGroup();
}
if (auto *childListParent{
child.parent().get_if<ChildListIoStatementState<DIR>>()}) {
// Child list I/O whose parent is child list I/O: can advance
// if the parent can.
this->canAdvance_ = childListParent->CanAdvance();
} else {
// Child list I/O of top-level list I/O: can advance.
this->canAdvance_ = true;
}
}
#else