[flang][runtime] Fix child input bugs under NAMELIST (#151571)
When NAMELIST input takes place on a derived type, we need to preserve the type in the descriptor that is created for storage sequence association. Further, the fact that any child list input in within the context of a NAMELIST must be inherited so that input fields don't try to consume later "variable=" strings. Fixes https://github.com/llvm/llvm-project/issues/151222.
This commit is contained in:
parent
cfd1ee781f
commit
aec90f2f27
@ -101,6 +101,9 @@ public:
|
||||
explicit RT_API_ATTRS DescriptorAddendum(
|
||||
const typeInfo::DerivedType *dt = nullptr)
|
||||
: derivedType_{dt}, len_{0} {}
|
||||
RT_API_ATTRS DescriptorAddendum(const DescriptorAddendum &that) {
|
||||
*this = that;
|
||||
}
|
||||
RT_API_ATTRS DescriptorAddendum &operator=(const DescriptorAddendum &);
|
||||
|
||||
RT_API_ATTRS const typeInfo::DerivedType *derivedType() const {
|
||||
|
@ -461,6 +461,9 @@ public:
|
||||
inNamelistSequence_ = inNamelistSequence;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool inNamelistSequence_{false};
|
||||
|
||||
private:
|
||||
int remaining_{0}; // for "r*" repetition
|
||||
Fortran::common::optional<SavedPosition> repeatPosition_;
|
||||
@ -468,7 +471,6 @@ private:
|
||||
bool hitSlash_{false}; // once '/' is seen, nullify further items
|
||||
bool realPart_{false};
|
||||
bool imaginaryPart_{false};
|
||||
bool inNamelistSequence_{false};
|
||||
};
|
||||
|
||||
template <Direction DIR>
|
||||
@ -688,7 +690,8 @@ template <Direction DIR>
|
||||
class ChildListIoStatementState : public ChildIoStatementState<DIR>,
|
||||
public ListDirectedStatementState<DIR> {
|
||||
public:
|
||||
using ChildIoStatementState<DIR>::ChildIoStatementState;
|
||||
RT_API_ATTRS ChildListIoStatementState(
|
||||
ChildIo &, const char *sourceFile = nullptr, int sourceLine = 0);
|
||||
using ListDirectedStatementState<DIR>::GetNextDataEdit;
|
||||
RT_API_ATTRS int EndIoStatement();
|
||||
};
|
||||
|
@ -110,7 +110,7 @@ static RT_API_ATTRS Fortran::common::optional<bool> DefinedFormattedIo(
|
||||
Fortran::common::optional<std::int64_t> startPos;
|
||||
if (edit.descriptor == DataEdit::DefinedDerivedType &&
|
||||
special.which() == typeInfo::SpecialBinding::Which::ReadFormatted) {
|
||||
// DT is an edit descriptor so everything that the child
|
||||
// DT is an edit descriptor, so everything that the child
|
||||
// I/O subroutine reads counts towards READ(SIZE=).
|
||||
startPos = io.InquirePos();
|
||||
}
|
||||
|
@ -231,6 +231,7 @@ RT_API_ATTRS bool Descriptor::EstablishPointerSection(const Descriptor &source,
|
||||
const SubscriptValue *stride) {
|
||||
*this = source;
|
||||
raw_.attribute = CFI_attribute_pointer;
|
||||
SetAllocIdx(source.GetAllocIdx());
|
||||
int newRank{raw_.rank};
|
||||
for (int j{0}; j < raw_.rank; ++j) {
|
||||
if (!stride || stride[j] == 0) {
|
||||
@ -242,6 +243,9 @@ RT_API_ATTRS bool Descriptor::EstablishPointerSection(const Descriptor &source,
|
||||
}
|
||||
}
|
||||
raw_.rank = newRank;
|
||||
if (CFI_section(&raw_, &source.raw_, lower, upper, stride) != CFI_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
if (const auto *sourceAddendum = source.Addendum()) {
|
||||
if (auto *addendum{Addendum()}) {
|
||||
*addendum = *sourceAddendum;
|
||||
@ -249,7 +253,7 @@ RT_API_ATTRS bool Descriptor::EstablishPointerSection(const Descriptor &source,
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return CFI_section(&raw_, &source.raw_, lower, upper, stride) == CFI_SUCCESS;
|
||||
return true;
|
||||
}
|
||||
|
||||
RT_API_ATTRS void Descriptor::ApplyMold(
|
||||
|
@ -1078,6 +1078,22 @@ bool ChildFormattedIoStatementState<DIR, CHAR>::AdvanceRecord(int n) {
|
||||
#endif
|
||||
}
|
||||
|
||||
template <Direction DIR>
|
||||
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 (auto *listInput{child.parent()
|
||||
.get_if<ListDirectedStatementState<Direction::Input>>()}) {
|
||||
this->inNamelistSequence_ = listInput->inNamelistSequence();
|
||||
}
|
||||
}
|
||||
#else
|
||||
this->ReportUnsupportedChildIo();
|
||||
#endif
|
||||
}
|
||||
|
||||
template <Direction DIR>
|
||||
bool ChildUnformattedIoStatementState<DIR>::Receive(
|
||||
char *data, std::size_t bytes, std::size_t elementBytes) {
|
||||
|
@ -268,6 +268,11 @@ static RT_API_ATTRS void StorageSequenceExtension(
|
||||
? source.GetDimension(0).ByteStride()
|
||||
: static_cast<SubscriptValue>(source.ElementBytes())};
|
||||
stride != 0) {
|
||||
common::optional<DescriptorAddendum> savedAddendum;
|
||||
if (const DescriptorAddendum *addendum{desc.Addendum()}) {
|
||||
// Preserve a copy of the addendum, if any, before clobbering it
|
||||
savedAddendum.emplace(*addendum);
|
||||
}
|
||||
desc.raw().attribute = CFI_attribute_pointer;
|
||||
desc.raw().rank = 1;
|
||||
desc.GetDimension(0)
|
||||
@ -275,6 +280,9 @@ static RT_API_ATTRS void StorageSequenceExtension(
|
||||
source.Elements() -
|
||||
((source.OffsetElement() - desc.OffsetElement()) / stride))
|
||||
.SetByteStride(stride);
|
||||
if (savedAddendum) {
|
||||
*desc.Addendum() = *savedAddendum;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user