mirror of
https://github.com/intel/llvm.git
synced 2026-01-13 02:38:07 +08:00
[flang][runtime] Disable namelist storage sequence input when defined (#158708)
The runtime supports a near-universal extension to namelist input that allows reading a sequence of values into a storage sequence beginning at an array element, e.g. &NML A(2)=1. 2. 3. / . Disable this extension when the type of the array has a defined formatted READ subroutine defined. That defined input procedure may itself not be using list-directed input, and might not notice a following slash or new input item name as such. Fixes https://github.com/llvm/llvm-project/issues/158496.
This commit is contained in:
@@ -258,13 +258,40 @@ static RT_API_ATTRS bool HandleSubscripts(IoStatementState &io,
|
||||
return false;
|
||||
}
|
||||
|
||||
static RT_API_ATTRS void StorageSequenceExtension(
|
||||
Descriptor &desc, const Descriptor &source) {
|
||||
static RT_API_ATTRS bool HasDefinedIoSubroutine(common::DefinedIo definedIo,
|
||||
typeInfo::SpecialBinding::Which specialBinding,
|
||||
const typeInfo::DerivedType *derivedType,
|
||||
const NonTbpDefinedIoTable *table) {
|
||||
for (; derivedType; derivedType = derivedType->GetParentType()) {
|
||||
if ((table && table->Find(*derivedType, definedIo) != nullptr) ||
|
||||
derivedType->FindSpecialBinding(specialBinding)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static RT_API_ATTRS bool HasDefinedIoSubroutine(common::DefinedIo definedIo,
|
||||
typeInfo::SpecialBinding::Which specialBinding,
|
||||
const Descriptor &descriptor, const NonTbpDefinedIoTable *table) {
|
||||
const DescriptorAddendum *addendum{descriptor.Addendum()};
|
||||
return addendum &&
|
||||
HasDefinedIoSubroutine(
|
||||
definedIo, specialBinding, addendum->derivedType(), table);
|
||||
}
|
||||
|
||||
static RT_API_ATTRS void StorageSequenceExtension(Descriptor &desc,
|
||||
const Descriptor &source, const io::NonTbpDefinedIoTable *table) {
|
||||
// Support the near-universal extension of NAMELIST input into a
|
||||
// designatable storage sequence identified by its initial scalar array
|
||||
// element. For example, treat "A(1) = 1. 2. 3." as if it had been
|
||||
// "A(1:) = 1. 2. 3.".
|
||||
if (desc.rank() == 0 && (source.rank() == 1 || source.IsContiguous())) {
|
||||
// (But don't do this for derived types with defined formatted READs,
|
||||
// since they might do non-list-directed input that won't stop at the
|
||||
// next namelist input item name.)
|
||||
if (desc.rank() == 0 && (source.rank() == 1 || source.IsContiguous()) &&
|
||||
!HasDefinedIoSubroutine(common::DefinedIo::ReadFormatted,
|
||||
typeInfo::SpecialBinding::Which::ReadFormatted, desc, table)) {
|
||||
if (auto stride{source.rank() == 1
|
||||
? source.GetDimension(0).ByteStride()
|
||||
: static_cast<SubscriptValue>(source.ElementBytes())};
|
||||
@@ -561,7 +588,8 @@ bool IODEF(InputNamelist)(Cookie cookie, const NamelistGroup &group) {
|
||||
next = io.GetCurrentChar(byteCount);
|
||||
} while (next && (*next == '(' || *next == '%'));
|
||||
if (lastSubscriptDescriptor) {
|
||||
StorageSequenceExtension(*lastSubscriptDescriptor, *lastSubscriptBase);
|
||||
StorageSequenceExtension(*lastSubscriptDescriptor, *lastSubscriptBase,
|
||||
group.nonTbpDefinedIo);
|
||||
}
|
||||
}
|
||||
// Skip the '='
|
||||
|
||||
@@ -930,3 +930,6 @@ print *, [(j,j=1,10)]
|
||||
or contiguous array can be used as the initial element of a storage
|
||||
sequence. For example, "&GRP A(1)=1. 2. 3./" is treated as if had been
|
||||
"&GRP A(1:)=1. 2. 3./".
|
||||
This extension is necessarily disabled when the type of the array
|
||||
has an accessible defined formatted READ subroutine.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user