@@ -300,12 +300,15 @@ static void ConvertLogicalActual(evaluate::Expr<evaluate::SomeType> &actual,
300
300
}
301
301
302
302
static bool DefersSameTypeParameters (
303
- const DerivedTypeSpec &actual, const DerivedTypeSpec &dummy) {
304
- for (const auto &pair : actual.parameters ()) {
305
- const ParamValue &actualValue{pair.second };
306
- const ParamValue *dummyValue{dummy.FindParameter (pair.first )};
307
- if (!dummyValue || (actualValue.isDeferred () != dummyValue->isDeferred ())) {
308
- return false ;
303
+ const DerivedTypeSpec *actual, const DerivedTypeSpec *dummy) {
304
+ if (actual && dummy) {
305
+ for (const auto &pair : actual->parameters ()) {
306
+ const ParamValue &actualValue{pair.second };
307
+ const ParamValue *dummyValue{dummy->FindParameter (pair.first )};
308
+ if (!dummyValue ||
309
+ (actualValue.isDeferred () != dummyValue->isDeferred ())) {
310
+ return false ;
311
+ }
309
312
}
310
313
}
311
314
return true ;
@@ -370,9 +373,37 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
370
373
}
371
374
bool dummyIsAssumedRank{dummy.type .attrs ().test (
372
375
characteristics::TypeAndShape::Attr::AssumedRank)};
376
+ bool actualIsAssumedSize{actualType.attrs ().test (
377
+ characteristics::TypeAndShape::Attr::AssumedSize)};
378
+ bool actualIsAssumedRank{evaluate::IsAssumedRank (actual)};
379
+ bool actualIsPointer{evaluate::IsObjectPointer (actual)};
380
+ bool actualIsAllocatable{evaluate::IsAllocatableDesignator (actual)};
381
+ bool actualMayBeAssumedSize{actualIsAssumedSize ||
382
+ (actualIsAssumedRank && !actualIsPointer && !actualIsAllocatable)};
383
+ bool actualIsPolymorphic{actualType.type ().IsPolymorphic ()};
384
+ const auto *actualDerived{evaluate::GetDerivedTypeSpec (actualType.type ())};
373
385
if (typesCompatible) {
374
386
if (isElemental) {
375
387
} else if (dummyIsAssumedRank) {
388
+ if (actualMayBeAssumedSize && dummy.intent == common::Intent::Out) {
389
+ // An INTENT(OUT) dummy might be a no-op at run time
390
+ bool dummyHasSignificantIntentOut{actualIsPolymorphic ||
391
+ (actualDerived &&
392
+ (actualDerived->HasDefaultInitialization (
393
+ /* ignoreAllocatable=*/ false , /* ignorePointer=*/ true ) ||
394
+ actualDerived->HasDestruction ()))};
395
+ const char *actualDesc{
396
+ actualIsAssumedSize ? " Assumed-size" : " Assumed-rank" };
397
+ if (dummyHasSignificantIntentOut) {
398
+ messages.Say (
399
+ " %s actual argument may not be associated with INTENT(OUT) assumed-rank dummy argument requiring finalization, destruction, or initialization" _err_en_US,
400
+ actualDesc);
401
+ } else {
402
+ context.Warn (common::UsageWarning::Portability, messages.at (),
403
+ " %s actual argument should not be associated with INTENT(OUT) assumed-rank dummy argument" _port_en_US,
404
+ actualDesc);
405
+ }
406
+ }
376
407
} else if (dummy.ignoreTKR .test (common::IgnoreTKR::Rank)) {
377
408
} else if (dummyRank > 0 && !dummyIsAllocatableOrPointer &&
378
409
!dummy.type .attrs ().test (
@@ -401,11 +432,7 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
401
432
dummy.type .type ().AsFortran ());
402
433
}
403
434
404
- bool actualIsPolymorphic{actualType.type ().IsPolymorphic ()};
405
- bool dummyIsPolymorphic{dummy.type .type ().IsPolymorphic ()};
406
435
bool actualIsCoindexed{ExtractCoarrayRef (actual).has_value ()};
407
- bool actualIsAssumedSize{actualType.attrs ().test (
408
- characteristics::TypeAndShape::Attr::AssumedSize)};
409
436
bool dummyIsAssumedSize{dummy.type .attrs ().test (
410
437
characteristics::TypeAndShape::Attr::AssumedSize)};
411
438
bool dummyIsAsynchronous{
@@ -414,7 +441,7 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
414
441
dummy.attrs .test (characteristics::DummyDataObject::Attr::Volatile)};
415
442
bool dummyIsValue{
416
443
dummy.attrs .test (characteristics::DummyDataObject::Attr::Value)};
417
-
444
+ bool dummyIsPolymorphic{dummy. type . type (). IsPolymorphic ()};
418
445
if (actualIsPolymorphic && dummyIsPolymorphic &&
419
446
actualIsCoindexed) { // 15.5.2.4(2)
420
447
messages.Say (
@@ -434,37 +461,36 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
434
461
actualFirstSymbol && actualFirstSymbol->attrs ().test (Attr::ASYNCHRONOUS)};
435
462
bool actualIsVolatile{
436
463
actualFirstSymbol && actualFirstSymbol->attrs ().test (Attr::VOLATILE)};
437
- const auto *derived{evaluate::GetDerivedTypeSpec (actualType.type ())};
438
- if (derived && !derived->IsVectorType ()) {
464
+ if (actualDerived && !actualDerived->IsVectorType ()) {
439
465
if (dummy.type .type ().IsAssumedType ()) {
440
- if (!derived ->parameters ().empty ()) { // 15.5.2.4(2)
466
+ if (!actualDerived ->parameters ().empty ()) { // 15.5.2.4(2)
441
467
messages.Say (
442
468
" Actual argument associated with TYPE(*) %s may not have a parameterized derived type" _err_en_US,
443
469
dummyName);
444
470
}
445
471
if (const Symbol *
446
- tbp{FindImmediateComponent (*derived , [](const Symbol &symbol) {
472
+ tbp{FindImmediateComponent (*actualDerived , [](const Symbol &symbol) {
447
473
return symbol.has <ProcBindingDetails>();
448
474
})}) { // 15.5.2.4(2)
449
475
evaluate::SayWithDeclaration (messages, *tbp,
450
476
" Actual argument associated with TYPE(*) %s may not have type-bound procedure '%s'" _err_en_US,
451
477
dummyName, tbp->name ());
452
478
}
453
- auto finals{FinalsForDerivedTypeInstantiation (*derived )};
479
+ auto finals{FinalsForDerivedTypeInstantiation (*actualDerived )};
454
480
if (!finals.empty ()) { // 15.5.2.4(2)
455
481
SourceName name{finals.front ()->name ()};
456
482
if (auto *msg{messages.Say (
457
483
" Actual argument associated with TYPE(*) %s may not have derived type '%s' with FINAL subroutine '%s'" _err_en_US,
458
- dummyName, derived ->typeSymbol ().name (), name)}) {
484
+ dummyName, actualDerived ->typeSymbol ().name (), name)}) {
459
485
msg->Attach (name, " FINAL subroutine '%s' in derived type '%s'" _en_US,
460
- name, derived ->typeSymbol ().name ());
486
+ name, actualDerived ->typeSymbol ().name ());
461
487
}
462
488
}
463
489
}
464
490
if (actualIsCoindexed) {
465
491
if (dummy.intent != common::Intent::In && !dummyIsValue) {
466
- if (auto bad{
467
- FindAllocatableUltimateComponent (*derived )}) { // 15.5.2.4(6)
492
+ if (auto bad{FindAllocatableUltimateComponent (
493
+ *actualDerived )}) { // 15.5.2.4(6)
468
494
evaluate::SayWithDeclaration (messages, *bad,
469
495
" Coindexed actual argument with ALLOCATABLE ultimate component '%s' must be associated with a %s with VALUE or INTENT(IN) attributes" _err_en_US,
470
496
bad.BuildResultDesignatorName (), dummyName);
@@ -484,7 +510,7 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
484
510
}
485
511
}
486
512
if (actualIsVolatile != dummyIsVolatile) { // 15.5.2.4(22)
487
- if (auto bad{semantics::FindCoarrayUltimateComponent (*derived )}) {
513
+ if (auto bad{semantics::FindCoarrayUltimateComponent (*actualDerived )}) {
488
514
evaluate::SayWithDeclaration (messages, *bad,
489
515
" VOLATILE attribute must match for %s when actual argument has a coarray ultimate component '%s'" _err_en_US,
490
516
dummyName, bad.BuildResultDesignatorName ());
@@ -501,8 +527,6 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
501
527
? actualLastSymbol->detailsIf <ObjectEntityDetails>()
502
528
: nullptr };
503
529
int actualRank{actualType.Rank ()};
504
- bool actualIsPointer{evaluate::IsObjectPointer (actual)};
505
- bool actualIsAssumedRank{evaluate::IsAssumedRank (actual)};
506
530
if (dummy.type .attrs ().test (
507
531
characteristics::TypeAndShape::Attr::AssumedShape)) {
508
532
// 15.5.2.4(16)
@@ -730,7 +754,6 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
730
754
}
731
755
732
756
// 15.5.2.6 -- dummy is ALLOCATABLE
733
- bool actualIsAllocatable{evaluate::IsAllocatableDesignator (actual)};
734
757
bool dummyIsOptional{
735
758
dummy.attrs .test (characteristics::DummyDataObject::Attr::Optional)};
736
759
bool actualIsNull{evaluate::IsNullPointer (actual)};
@@ -851,10 +874,8 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
851
874
}
852
875
}
853
876
// 15.5.2.5(4)
854
- const auto *derived{evaluate::GetDerivedTypeSpec (actualType.type ())};
855
- if ((derived &&
856
- !DefersSameTypeParameters (*derived,
857
- *evaluate::GetDerivedTypeSpec (dummy.type .type ()))) ||
877
+ const auto *dummyDerived{evaluate::GetDerivedTypeSpec (dummy.type .type ())};
878
+ if (!DefersSameTypeParameters (actualDerived, dummyDerived) ||
858
879
dummy.type .type ().HasDeferredTypeParameter () !=
859
880
actualType.type ().HasDeferredTypeParameter ()) {
860
881
messages.Say (
0 commit comments