[flang][runtime] Allow INQUIRE(IOLENGTH=) in the presence of defined I/O (#144541)
When I/O list items include instances of derived types for which defined I/O procedures exist, ignore them. Fixes https://github.com/llvm/llvm-project/issues/144363.
This commit is contained in:
@@ -451,39 +451,42 @@ RT_API_ATTRS int DescriptorIoTicket<DIR>::Begin(WorkQueue &workQueue) {
|
|||||||
if (const typeInfo::DerivedType *type{
|
if (const typeInfo::DerivedType *type{
|
||||||
addendum ? addendum->derivedType() : nullptr}) {
|
addendum ? addendum->derivedType() : nullptr}) {
|
||||||
// derived type unformatted I/O
|
// derived type unformatted I/O
|
||||||
if (table_) {
|
if (DIR == Direction::Input || !io_.get_if<InquireIOLengthState>()) {
|
||||||
if (const auto *definedIo{table_->Find(*type,
|
if (table_) {
|
||||||
DIR == Direction::Input
|
if (const auto *definedIo{table_->Find(*type,
|
||||||
? common::DefinedIo::ReadUnformatted
|
DIR == Direction::Input
|
||||||
: common::DefinedIo::WriteUnformatted)}) {
|
? common::DefinedIo::ReadUnformatted
|
||||||
if (definedIo->subroutine) {
|
: common::DefinedIo::WriteUnformatted)}) {
|
||||||
typeInfo::SpecialBinding special{DIR == Direction::Input
|
if (definedIo->subroutine) {
|
||||||
? typeInfo::SpecialBinding::Which::ReadUnformatted
|
typeInfo::SpecialBinding special{DIR == Direction::Input
|
||||||
: typeInfo::SpecialBinding::Which::WriteUnformatted,
|
? typeInfo::SpecialBinding::Which::ReadUnformatted
|
||||||
definedIo->subroutine, definedIo->isDtvArgPolymorphic, false,
|
: typeInfo::SpecialBinding::Which::WriteUnformatted,
|
||||||
false};
|
definedIo->subroutine, definedIo->isDtvArgPolymorphic, false,
|
||||||
if (DefinedUnformattedIo(io_, instance_, *type, special)) {
|
false};
|
||||||
anyIoTookPlace_ = true;
|
if (DefinedUnformattedIo(io_, instance_, *type, special)) {
|
||||||
return StatOk;
|
anyIoTookPlace_ = true;
|
||||||
|
return StatOk;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int status{workQueue.BeginDerivedIo<DIR>(
|
||||||
|
io_, instance_, *type, table_, anyIoTookPlace_)};
|
||||||
|
return status == StatContinue ? StatOk : status; // done here
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
int status{workQueue.BeginDerivedIo<DIR>(
|
|
||||||
io_, instance_, *type, table_, anyIoTookPlace_)};
|
|
||||||
return status == StatContinue ? StatOk : status; // done here
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
if (const typeInfo::SpecialBinding *special{
|
||||||
if (const typeInfo::SpecialBinding *special{
|
type->FindSpecialBinding(DIR == Direction::Input
|
||||||
type->FindSpecialBinding(DIR == Direction::Input
|
? typeInfo::SpecialBinding::Which::ReadUnformatted
|
||||||
? typeInfo::SpecialBinding::Which::ReadUnformatted
|
: typeInfo::SpecialBinding::Which::WriteUnformatted)}) {
|
||||||
: typeInfo::SpecialBinding::Which::WriteUnformatted)}) {
|
if (!table_ || !table_->ignoreNonTbpEntries ||
|
||||||
if (!table_ || !table_->ignoreNonTbpEntries || special->IsTypeBound()) {
|
special->IsTypeBound()) {
|
||||||
// defined derived type unformatted I/O
|
// defined derived type unformatted I/O
|
||||||
if (DefinedUnformattedIo(io_, instance_, *type, *special)) {
|
if (DefinedUnformattedIo(io_, instance_, *type, *special)) {
|
||||||
anyIoTookPlace_ = true;
|
anyIoTookPlace_ = true;
|
||||||
return StatOk;
|
return StatOk;
|
||||||
} else {
|
} else {
|
||||||
return IostatEnd;
|
return IostatEnd;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -868,6 +868,13 @@ print *, [(j,j=1,10)]
|
|||||||
the elements for each component before proceeding to the next component.
|
the elements for each component before proceeding to the next component.
|
||||||
A program using defined assignment might be able to detect the difference.
|
A program using defined assignment might be able to detect the difference.
|
||||||
|
|
||||||
|
* The standard forbids instances of derived types with defined unformatted
|
||||||
|
WRITE subroutines from appearing in the I/O list of an `INQUIRE(IOLENGTH=...)`
|
||||||
|
statement. It then also says that these defined I/O procedures should be
|
||||||
|
ignored for that statement. So we allow them to appear (like most
|
||||||
|
compilers) and don't use any defined unformatted WRITE that might have been
|
||||||
|
defined.
|
||||||
|
|
||||||
## De Facto Standard Features
|
## De Facto Standard Features
|
||||||
|
|
||||||
* `EXTENDS_TYPE_OF()` returns `.TRUE.` if both of its arguments have the
|
* `EXTENDS_TYPE_OF()` returns `.TRUE.` if both of its arguments have the
|
||||||
|
|||||||
Reference in New Issue
Block a user