SomeExpr PackageIntValueExpr(const SomeExpr &genre, std::int64_t = 0) const;
std::vector<evaluate::StructureConstructor> DescribeBindings(
const Scope &dtScope, Scope &);
- void DescribeGeneric(
- const GenericDetails &, std::map<int, evaluate::StructureConstructor> &);
+ void DescribeGeneric(const GenericDetails &,
+ std::map<int, evaluate::StructureConstructor> &, const DerivedTypeSpec *);
void DescribeSpecialProc(std::map<int, evaluate::StructureConstructor> &,
const Symbol &specificOrBinding, bool isAssignment, bool isFinal,
- std::optional<GenericKind::DefinedIo>);
+ std::optional<GenericKind::DefinedIo>, const DerivedTypeSpec *);
void IncorporateDefinedIoGenericInterfaces(
std::map<int, evaluate::StructureConstructor> &, GenericKind::DefinedIo,
- const Scope *);
+ const Scope *, const DerivedTypeSpec *);
// Instantiated for ParamValue and Bound
template <typename A>
[&](const ProcBindingDetails &) { // handled in a later pass
},
[&](const GenericDetails &generic) {
- DescribeGeneric(generic, specials);
+ DescribeGeneric(generic, specials, derivedTypeSpec);
},
[&](const auto &) {
common::die(
const DerivedTypeDetails &dtDetails{dtSymbol->get<DerivedTypeDetails>()};
for (const auto &pair : dtDetails.finals()) {
DescribeSpecialProc(specials, *pair.second, false /*!isAssignment*/,
- true, std::nullopt);
+ true, std::nullopt, derivedTypeSpec);
+ }
+ if (derivedTypeSpec) {
+ IncorporateDefinedIoGenericInterfaces(specials,
+ GenericKind::DefinedIo::ReadFormatted, &scope, derivedTypeSpec);
+ IncorporateDefinedIoGenericInterfaces(specials,
+ GenericKind::DefinedIo::ReadUnformatted, &scope, derivedTypeSpec);
+ IncorporateDefinedIoGenericInterfaces(specials,
+ GenericKind::DefinedIo::WriteFormatted, &scope, derivedTypeSpec);
+ IncorporateDefinedIoGenericInterfaces(specials,
+ GenericKind::DefinedIo::WriteUnformatted, &scope, derivedTypeSpec);
}
- IncorporateDefinedIoGenericInterfaces(
- specials, GenericKind::DefinedIo::ReadFormatted, &scope);
- IncorporateDefinedIoGenericInterfaces(
- specials, GenericKind::DefinedIo::ReadUnformatted, &scope);
- IncorporateDefinedIoGenericInterfaces(
- specials, GenericKind::DefinedIo::WriteFormatted, &scope);
- IncorporateDefinedIoGenericInterfaces(
- specials, GenericKind::DefinedIo::WriteUnformatted, &scope);
// Pack the special procedure bindings in ascending order of their "which"
// code values, and compile a little-endian bit-set of those codes for
// use in O(1) look-up at run time.
}
void RuntimeTableBuilder::DescribeGeneric(const GenericDetails &generic,
- std::map<int, evaluate::StructureConstructor> &specials) {
+ std::map<int, evaluate::StructureConstructor> &specials,
+ const DerivedTypeSpec *derivedTypeSpec) {
common::visit(common::visitors{
[&](const GenericKind::OtherKind &k) {
if (k == GenericKind::OtherKind::Assignment) {
for (auto ref : generic.specificProcs()) {
DescribeSpecialProc(specials, *ref, true,
- false /*!final*/, std::nullopt);
+ false /*!final*/, std::nullopt, derivedTypeSpec);
}
}
},
case GenericKind::DefinedIo::WriteFormatted:
case GenericKind::DefinedIo::WriteUnformatted:
for (auto ref : generic.specificProcs()) {
- DescribeSpecialProc(
- specials, *ref, false, false /*!final*/, io);
+ DescribeSpecialProc(specials, *ref, false,
+ false /*!final*/, io, derivedTypeSpec);
}
break;
}
void RuntimeTableBuilder::DescribeSpecialProc(
std::map<int, evaluate::StructureConstructor> &specials,
const Symbol &specificOrBinding, bool isAssignment, bool isFinal,
- std::optional<GenericKind::DefinedIo> io) {
+ std::optional<GenericKind::DefinedIo> io,
+ const DerivedTypeSpec *derivedTypeSpec) {
const auto *binding{specificOrBinding.detailsIf<ProcBindingDetails>()};
const Symbol &specific{*(binding ? &binding->symbol() : &specificOrBinding)};
if (auto proc{evaluate::characteristics::Procedure::Characterize(
}
} else { // user defined derived type I/O
CHECK(proc->dummyArguments.size() >= 4);
+ if (derivedTypeSpec &&
+ !std::get<evaluate::characteristics::DummyDataObject>(
+ proc->dummyArguments[0].u)
+ .type.type()
+ .IsTkCompatibleWith(evaluate::DynamicType{*derivedTypeSpec})) {
+ // Defined I/O specific procedure is not for this derived type.
+ return;
+ }
if (binding) {
isArgDescriptorSet |= 1;
}
void RuntimeTableBuilder::IncorporateDefinedIoGenericInterfaces(
std::map<int, evaluate::StructureConstructor> &specials,
- GenericKind::DefinedIo definedIo, const Scope *scope) {
+ GenericKind::DefinedIo definedIo, const Scope *scope,
+ const DerivedTypeSpec *derivedTypeSpec) {
SourceName name{GenericKind::AsFortran(definedIo)};
for (; !scope->IsGlobal(); scope = &scope->parent()) {
if (auto asst{scope->find(name)}; asst != scope->end()) {
CHECK(std::get<GenericKind::DefinedIo>(genericDetails.kind().u) ==
definedIo);
for (auto ref : genericDetails.specificProcs()) {
- DescribeSpecialProc(specials, *ref, false, false, definedIo);
+ DescribeSpecialProc(
+ specials, *ref, false, false, definedIo, derivedTypeSpec);
}
}
}
--- /dev/null
+! RUN: %python %S/test_errors.py %s %flang_fc1
+! Check for distinguishability of defined I/O procedures defined within
+! and outside their types.
+module m1
+ type t1
+ integer n
+ contains
+ procedure :: readt1a, readt1b
+ !ERROR: Generic 'read(unformatted)' may not have specific procedures 'readt1a' and 'readt1b' as their interfaces are not distinguishable
+ generic :: read(unformatted) => readt1a, readt1b
+ end type
+ type t2
+ integer n
+ end type
+ type t3
+ integer n
+ end type
+ !ERROR: Generic 'read(unformatted)' may not have specific procedures 'readt2a' and 'readt2b' as their interfaces are not distinguishable
+ interface read(unformatted)
+ module procedure :: readt1a, readt2a, readt2b, readt3
+ end interface
+ contains
+#define DEFINE_READU(name, type) \
+ subroutine name(dtv, unit, iostat, iomsg); \
+ class(type), intent(in out) :: dtv; \
+ integer, intent(in) :: unit; \
+ integer, intent(out) :: iostat; \
+ character(*), intent(in out) :: iomsg; \
+ read(unit, iostat=iostat, iomsg=iomsg) dtv%n; \
+ end subroutine name
+ !ERROR: Derived type 't1' already has defined input/output procedure 'read(unformatted)'
+ DEFINE_READU(readt1a, t1)
+ DEFINE_READU(readt1b, t1)
+ DEFINE_READU(readt2a, t2)
+ DEFINE_READU(readt2b, t2)
+ DEFINE_READU(readt3, t3)
+end module
character(*),intent(inout) :: iomsg
read(unit,iotype,iostat=iostat,iomsg=iomsg) dtv%c
end subroutine
- !ERROR: Derived type 't' already has defined input/output procedure 'READUNFORMATTED'
+ !ERROR: Derived type 't' already has defined input/output procedure 'read(unformatted)'
subroutine unformattedReadProc(dtv,unit,iostat,iomsg)
class(t),intent(inout) :: dtv
integer,intent(in) :: unit
character(*),intent(inout) :: iomsg
read(unit,iotype,iostat=iostat,iomsg=iomsg) dtv%c
end subroutine
- !ERROR: Derived type 't' already has defined input/output procedure 'READUNFORMATTED'
+ !ERROR: Derived type 't' already has defined input/output procedure 'read(unformatted)'
subroutine unformattedReadProc1(dtv,unit,iostat,iomsg)
class(t(4)),intent(inout) :: dtv
integer,intent(in) :: unit
character(*),intent(inout) :: iomsg
read(unit,iotype,iostat=iostat,iomsg=iomsg) dtv%c
end subroutine
- !ERROR: Derived type 't' already has defined input/output procedure 'READUNFORMATTED'
+ !ERROR: Derived type 't' already has defined input/output procedure 'read(unformatted)'
subroutine unformattedReadProc1(dtv,unit,iostat,iomsg)
class(t(*)),intent(inout) :: dtv
integer,intent(in) :: unit