@@ -268,7 +268,33 @@ static bool DefaultComponentIO(IoStatementState &io,
268
268
}
269
269
270
270
template <Direction DIR>
271
- static bool DefaultComponentwiseIO (IoStatementState &io,
271
+ static bool DefaultComponentwiseFormattedIO (IoStatementState &io,
272
+ const Descriptor &descriptor, const typeInfo::DerivedType &type,
273
+ const NonTbpDefinedIoTable *table, const SubscriptValue subscripts[]) {
274
+ IoErrorHandler &handler{io.GetIoErrorHandler ()};
275
+ const Descriptor &compArray{type.component ()};
276
+ RUNTIME_CHECK (handler, compArray.rank () == 1 );
277
+ std::size_t numComponents{compArray.Elements ()};
278
+ SubscriptValue at[maxRank];
279
+ compArray.GetLowerBounds (at);
280
+ for (std::size_t k{0 }; k < numComponents;
281
+ ++k, compArray.IncrementSubscripts (at)) {
282
+ const typeInfo::Component &component{
283
+ *compArray.Element <typeInfo::Component>(at)};
284
+ if (!DefaultComponentIO<DIR>(
285
+ io, component, descriptor, subscripts, handler, table)) {
286
+ // Return true for NAMELIST input if any component appeared.
287
+ auto *listInput{
288
+ io.get_if <ListDirectedStatementState<Direction::Input>>()};
289
+ return DIR == Direction::Input && k > 0 && listInput &&
290
+ listInput->inNamelistSequence ();
291
+ }
292
+ }
293
+ return true ;
294
+ }
295
+
296
+ template <Direction DIR>
297
+ static bool DefaultComponentwiseUnformattedIO (IoStatementState &io,
272
298
const Descriptor &descriptor, const typeInfo::DerivedType &type,
273
299
const NonTbpDefinedIoTable *table) {
274
300
IoErrorHandler &handler{io.GetIoErrorHandler ()};
@@ -288,19 +314,16 @@ static bool DefaultComponentwiseIO(IoStatementState &io,
288
314
*compArray.Element <typeInfo::Component>(at)};
289
315
if (!DefaultComponentIO<DIR>(
290
316
io, component, descriptor, subscripts, handler, table)) {
291
- // Truncated nonempty namelist input sequence?
292
- auto *listInput{
293
- io.get_if <ListDirectedStatementState<Direction::Input>>()};
294
- return DIR == Direction::Input && (j > 0 || k > 0 ) && listInput &&
295
- listInput->inNamelistSequence ();
317
+ return false ;
296
318
}
297
319
}
298
320
}
299
321
return true ;
300
322
}
301
323
302
324
std::optional<bool > DefinedFormattedIo (IoStatementState &, const Descriptor &,
303
- const typeInfo::DerivedType &, const typeInfo::SpecialBinding &);
325
+ const typeInfo::DerivedType &, const typeInfo::SpecialBinding &,
326
+ const SubscriptValue[]);
304
327
305
328
template <Direction DIR>
306
329
static bool FormattedDerivedTypeIO (IoStatementState &io,
@@ -311,37 +334,54 @@ static bool FormattedDerivedTypeIO(IoStatementState &io,
311
334
RUNTIME_CHECK (handler, addendum != nullptr );
312
335
const typeInfo::DerivedType *type{addendum->derivedType ()};
313
336
RUNTIME_CHECK (handler, type != nullptr );
337
+ std::optional<typeInfo::SpecialBinding> nonTbpSpecial;
338
+ const typeInfo::SpecialBinding *special{nullptr };
314
339
if (table) {
315
340
if (const auto *definedIo{table->Find (*type,
316
341
DIR == Direction::Input ? common::DefinedIo::ReadFormatted
317
342
: common::DefinedIo::WriteFormatted)}) {
318
343
if (definedIo->subroutine ) {
319
- typeInfo::SpecialBinding special{ DIR == Direction::Input
344
+ nonTbpSpecial. emplace ( DIR == Direction::Input
320
345
? typeInfo::SpecialBinding::Which::ReadFormatted
321
346
: typeInfo::SpecialBinding::Which::WriteFormatted,
322
347
definedIo->subroutine , definedIo->isDtvArgPolymorphic , false ,
323
- false };
324
- if (std::optional<bool > wasDefined{
325
- DefinedFormattedIo (io, descriptor, *type, special)}) {
326
- return *wasDefined;
327
- }
328
- } else {
329
- return DefaultComponentwiseIO<DIR>(io, descriptor, *type, table);
348
+ false );
349
+ special = &*nonTbpSpecial;
330
350
}
331
351
}
332
352
}
333
- if (const typeInfo::SpecialBinding *
334
- special{type->FindSpecialBinding (DIR == Direction::Input
335
- ? typeInfo::SpecialBinding::Which::ReadFormatted
336
- : typeInfo::SpecialBinding::Which::WriteFormatted)}) {
337
- if (!table || !table->ignoreNonTbpEntries || special->isTypeBound ()) {
338
- if (std::optional<bool > wasDefined{
339
- DefinedFormattedIo (io, descriptor, *type, *special)}) {
340
- return *wasDefined; // defined I/O was applied
353
+ if (!special) {
354
+ if (const typeInfo::SpecialBinding *
355
+ binding{type->FindSpecialBinding (DIR == Direction::Input
356
+ ? typeInfo::SpecialBinding::Which::ReadFormatted
357
+ : typeInfo::SpecialBinding::Which::WriteFormatted)}) {
358
+ if (!table || !table->ignoreNonTbpEntries || binding->isTypeBound ()) {
359
+ special = binding;
341
360
}
342
361
}
343
362
}
344
- return DefaultComponentwiseIO<DIR>(io, descriptor, *type, table);
363
+ SubscriptValue subscripts[maxRank];
364
+ descriptor.GetLowerBounds (subscripts);
365
+ std::size_t numElements{descriptor.Elements ()};
366
+ for (std::size_t j{0 }; j < numElements;
367
+ ++j, descriptor.IncrementSubscripts (subscripts)) {
368
+ std::optional<bool > result;
369
+ if (special) {
370
+ result = DefinedFormattedIo (io, descriptor, *type, *special, subscripts);
371
+ }
372
+ if (!result) {
373
+ result = DefaultComponentwiseFormattedIO<DIR>(
374
+ io, descriptor, *type, table, subscripts);
375
+ }
376
+ if (!result.value ()) {
377
+ // Return true for NAMELIST input if we got anything.
378
+ auto *listInput{
379
+ io.get_if <ListDirectedStatementState<Direction::Input>>()};
380
+ return DIR == Direction::Input && j > 0 && listInput &&
381
+ listInput->inNamelistSequence ();
382
+ }
383
+ }
384
+ return true ;
345
385
}
346
386
347
387
bool DefinedUnformattedIo (IoStatementState &, const Descriptor &,
@@ -371,7 +411,8 @@ static bool UnformattedDescriptorIO(IoStatementState &io,
371
411
return *wasDefined;
372
412
}
373
413
} else {
374
- return DefaultComponentwiseIO<DIR>(io, descriptor, *type, table);
414
+ return DefaultComponentwiseUnformattedIO<DIR>(
415
+ io, descriptor, *type, table);
375
416
}
376
417
}
377
418
}
@@ -388,7 +429,7 @@ static bool UnformattedDescriptorIO(IoStatementState &io,
388
429
// TODO: If no component at any level has defined READ or WRITE
389
430
// (as appropriate), the elements are contiguous, and no byte swapping
390
431
// is active, do a block transfer via the code below.
391
- return DefaultComponentwiseIO <DIR>(io, descriptor, *type, table);
432
+ return DefaultComponentwiseUnformattedIO <DIR>(io, descriptor, *type, table);
392
433
} else {
393
434
// intrinsic type unformatted I/O
394
435
auto *externalUnf{io.get_if <ExternalUnformattedIoStatementState<DIR>>()};
0 commit comments