@@ -165,8 +165,8 @@ class CheckHelper {
165165 void CheckDioDummyIsDefaultInteger (const Symbol &, const Symbol &);
166166 void CheckDioDummyIsScalar (const Symbol &, const Symbol &);
167167 void CheckDioDummyAttrs (const Symbol &, const Symbol &, Attr);
168- void CheckDioDtvArg (
169- const Symbol &, const Symbol *, common::DefinedIo, const Symbol &);
168+ void CheckDioDtvArg (const Symbol &proc, const Symbol &subp, const Symbol *arg,
169+ common::DefinedIo, const Symbol &generic );
170170 void CheckGenericVsIntrinsic (const Symbol &, const GenericDetails &);
171171 void CheckDefaultIntegerArg (const Symbol &, const Symbol *, Attr);
172172 void CheckDioAssumedLenCharacterArg (
@@ -3428,11 +3428,17 @@ void CheckHelper::CheckAlreadySeenDefinedIo(const DerivedTypeSpec &derivedType,
34283428 if (auto iter{dtScope->find (generic.name ())}; iter != dtScope->end () &&
34293429 IsAccessible (*iter->second , generic.owner ())) {
34303430 for (auto specRef : iter->second ->get <GenericDetails>().specificProcs ()) {
3431- const Symbol & specific{specRef->get <ProcBindingDetails>().symbol ()};
3432- if (specific == proc) {
3431+ const Symbol * specific{& specRef->get <ProcBindingDetails>().symbol ()};
3432+ if (specific == & proc) {
34333433 continue ; // unambiguous, accept
34343434 }
3435- if (const auto *specDT{GetDtvArgDerivedType (specific)};
3435+ if (const auto *peDetails{specific->detailsIf <ProcEntityDetails>()}) {
3436+ specific = peDetails->procInterface ();
3437+ if (!specific) {
3438+ continue ;
3439+ }
3440+ }
3441+ if (const auto *specDT{GetDtvArgDerivedType (*specific)};
34363442 specDT && evaluate::AreSameDerivedType (derivedType, *specDT)) {
34373443 SayWithDeclaration (*specRef, proc.name (),
34383444 " Derived type '%s' has conflicting type-bound input/output procedure '%s'" _err_en_US,
@@ -3444,11 +3450,11 @@ void CheckHelper::CheckAlreadySeenDefinedIo(const DerivedTypeSpec &derivedType,
34443450 }
34453451}
34463452
3447- void CheckHelper::CheckDioDummyIsDerived (const Symbol &subp , const Symbol &arg,
3453+ void CheckHelper::CheckDioDummyIsDerived (const Symbol &proc , const Symbol &arg,
34483454 common::DefinedIo ioKind, const Symbol &generic) {
34493455 if (const DeclTypeSpec *type{arg.GetType ()}) {
34503456 if (const DerivedTypeSpec *derivedType{type->AsDerived ()}) {
3451- CheckAlreadySeenDefinedIo (*derivedType, ioKind, subp , generic);
3457+ CheckAlreadySeenDefinedIo (*derivedType, ioKind, proc , generic);
34523458 bool isPolymorphic{type->IsPolymorphic ()};
34533459 if (isPolymorphic != IsExtensibleType (derivedType)) {
34543460 messages_.Say (arg.name (),
@@ -3486,11 +3492,11 @@ void CheckHelper::CheckDioDummyIsScalar(const Symbol &subp, const Symbol &arg) {
34863492 }
34873493}
34883494
3489- void CheckHelper::CheckDioDtvArg (const Symbol &subp , const Symbol *arg ,
3490- common::DefinedIo ioKind, const Symbol &generic) {
3495+ void CheckHelper::CheckDioDtvArg (const Symbol &proc , const Symbol &subp ,
3496+ const Symbol *arg, common::DefinedIo ioKind, const Symbol &generic) {
34913497 // Dtv argument looks like: dtv-type-spec, INTENT(INOUT) :: dtv
34923498 if (CheckDioDummyIsData (subp, arg, 0 )) {
3493- CheckDioDummyIsDerived (subp , *arg, ioKind, generic);
3499+ CheckDioDummyIsDerived (proc , *arg, ioKind, generic);
34943500 CheckDioDummyAttrs (subp, *arg,
34953501 ioKind == common::DefinedIo::ReadFormatted ||
34963502 ioKind == common::DefinedIo::ReadUnformatted
@@ -3617,57 +3623,64 @@ void CheckHelper::CheckDefinedIoProc(const Symbol &symbol,
36173623 for (auto ref : details.specificProcs ()) {
36183624 const Symbol &ultimate{ref->GetUltimate ()};
36193625 const auto *binding{ultimate.detailsIf <ProcBindingDetails>()};
3620- const Symbol &specific{*(binding ? &binding->symbol () : &ultimate)};
36213626 if (ultimate.attrs ().test (Attr::NOPASS)) { // C774
36223627 messages_.Say (
36233628 " Defined input/output procedure '%s' may not have NOPASS attribute" _err_en_US,
36243629 ultimate.name ());
36253630 context_.SetError (ultimate);
36263631 }
3627- if (const auto *subpDetails{specific.detailsIf <SubprogramDetails>()}) {
3632+ const Symbol *specificProc{binding ? &binding->symbol () : &ultimate};
3633+ const Symbol *specificSubp{specificProc};
3634+ if (const auto *peDetails{specificSubp->detailsIf <ProcEntityDetails>()}) {
3635+ specificSubp = peDetails->procInterface ();
3636+ if (!specificSubp) {
3637+ continue ;
3638+ }
3639+ }
3640+ if (const auto *subpDetails{specificSubp->detailsIf <SubprogramDetails>()}) {
36283641 const std::vector<Symbol *> &dummyArgs{subpDetails->dummyArgs ()};
3629- CheckDioArgCount (specific , ioKind, dummyArgs.size ());
3642+ CheckDioArgCount (*specificSubp , ioKind, dummyArgs.size ());
36303643 int argCount{0 };
36313644 for (auto *arg : dummyArgs) {
36323645 switch (argCount++) {
36333646 case 0 :
36343647 // dtv-type-spec, INTENT(INOUT) :: dtv
3635- CheckDioDtvArg (specific , arg, ioKind, symbol);
3648+ CheckDioDtvArg (*specificProc, *specificSubp , arg, ioKind, symbol);
36363649 break ;
36373650 case 1 :
36383651 // INTEGER, INTENT(IN) :: unit
3639- CheckDefaultIntegerArg (specific , arg, Attr::INTENT_IN);
3652+ CheckDefaultIntegerArg (*specificSubp , arg, Attr::INTENT_IN);
36403653 break ;
36413654 case 2 :
36423655 if (ioKind == common::DefinedIo::ReadFormatted ||
36433656 ioKind == common::DefinedIo::WriteFormatted) {
36443657 // CHARACTER (LEN=*), INTENT(IN) :: iotype
36453658 CheckDioAssumedLenCharacterArg (
3646- specific , arg, argCount, Attr::INTENT_IN);
3659+ *specificSubp , arg, argCount, Attr::INTENT_IN);
36473660 } else {
36483661 // INTEGER, INTENT(OUT) :: iostat
3649- CheckDefaultIntegerArg (specific , arg, Attr::INTENT_OUT);
3662+ CheckDefaultIntegerArg (*specificSubp , arg, Attr::INTENT_OUT);
36503663 }
36513664 break ;
36523665 case 3 :
36533666 if (ioKind == common::DefinedIo::ReadFormatted ||
36543667 ioKind == common::DefinedIo::WriteFormatted) {
36553668 // INTEGER, INTENT(IN) :: v_list(:)
3656- CheckDioVlistArg (specific , arg, argCount);
3669+ CheckDioVlistArg (*specificSubp , arg, argCount);
36573670 } else {
36583671 // CHARACTER (LEN=*), INTENT(INOUT) :: iomsg
36593672 CheckDioAssumedLenCharacterArg (
3660- specific , arg, argCount, Attr::INTENT_INOUT);
3673+ *specificSubp , arg, argCount, Attr::INTENT_INOUT);
36613674 }
36623675 break ;
36633676 case 4 :
36643677 // INTEGER, INTENT(OUT) :: iostat
3665- CheckDefaultIntegerArg (specific , arg, Attr::INTENT_OUT);
3678+ CheckDefaultIntegerArg (*specificSubp , arg, Attr::INTENT_OUT);
36663679 break ;
36673680 case 5 :
36683681 // CHARACTER (LEN=*), INTENT(INOUT) :: iomsg
36693682 CheckDioAssumedLenCharacterArg (
3670- specific , arg, argCount, Attr::INTENT_INOUT);
3683+ *specificSubp , arg, argCount, Attr::INTENT_INOUT);
36713684 break ;
36723685 default :;
36733686 }
0 commit comments