summaryrefslogtreecommitdiff
path: root/flang-rt
diff options
context:
space:
mode:
authorPeter Klausler <pklausler@nvidia.com>2025-09-17 09:14:32 -0700
committerGitHub <noreply@github.com>2025-09-17 09:14:32 -0700
commitbf684e0f2f97c56cdea9e36b6dacde48dc5cc269 (patch)
tree4e931bad6af005eda3483e197174e6039453a963 /flang-rt
parent6922f0e0aca40c9a5d160da89453443f902c2951 (diff)
[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.
Diffstat (limited to 'flang-rt')
-rw-r--r--flang-rt/lib/runtime/namelist.cpp36
1 files changed, 32 insertions, 4 deletions
diff --git a/flang-rt/lib/runtime/namelist.cpp b/flang-rt/lib/runtime/namelist.cpp
index 79dbe4b82292..47b16433e631 100644
--- a/flang-rt/lib/runtime/namelist.cpp
+++ b/flang-rt/lib/runtime/namelist.cpp
@@ -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 '='