Skip to content

Commit dc78329

Browse files
authored
[flang] Extension: associating polymorphic pointer/allocatable actual… (#93211)
… with monomorphic dummy The relevant standard requires (F'2023 15.5.2.6 p2) that when a pointer or allocatable actual argument is associated with an identically-attributed dummy argument, either both are polymorphic or neither is. We already relax this requirement in the case of an INTENT(IN) dummy argument, since a change of type cannot occur. Further, like other compilers do, we can also relax this requirement in the case of a limited polymorphic actual argument being associated with a monomorphic dummy, as our implementation always passes a reference to the actual descriptor, where any change of type that occurs during the call due to reallocation will be properly recorded.
1 parent 83b3e13 commit dc78329

File tree

4 files changed

+24
-6
lines changed

4 files changed

+24
-6
lines changed

flang/docs/Extensions.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,10 @@ end
223223
* When a dummy argument is `POINTER` or `ALLOCATABLE` and is `INTENT(IN)`, we
224224
relax enforcement of some requirements on actual arguments that must otherwise
225225
hold true for definable arguments.
226+
* We allow a limited polymorphic `POINTER` or `ALLOCATABLE` actual argument
227+
to be associated with a compatible monomorphic dummy argument, as
228+
our implementation, like others, supports a reallocation that would
229+
change the dynamic type
226230
* Assignment of `LOGICAL` to `INTEGER` and vice versa (but not other types) is
227231
allowed. The values are normalized to canonical `.TRUE.`/`.FALSE.`.
228232
The values are also normalized for assignments of `LOGICAL(KIND=K1)` to

flang/include/flang/Common/Fortran-features.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ ENUM_CLASS(LanguageFeature, BackslashEscapes, OldDebugLines,
4949
IndistinguishableSpecifics, SubroutineAndFunctionSpecifics,
5050
EmptySequenceType, NonSequenceCrayPointee, BranchIntoConstruct,
5151
BadBranchTarget, ConvertedArgument, HollerithPolymorphic, ListDirectedSize,
52-
NonBindCInteroperability, CudaManaged, CudaUnified)
52+
NonBindCInteroperability, CudaManaged, CudaUnified,
53+
PolymorphicActualAllocatableOrPointerToMonomorphicDummy)
5354

5455
// Portability and suspicious usage warnings
5556
ENUM_CLASS(UsageWarning, Portability, PointerToUndefinable,

flang/lib/Semantics/check-call.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -761,7 +761,8 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
761761
}
762762

763763
// 15.5.2.5 -- actual & dummy are both POINTER or both ALLOCATABLE
764-
// For INTENT(IN) we relax two checks that are in Fortran to
764+
// For INTENT(IN), and for a polymorphic actual being associated with a
765+
// monomorphic dummy, we relax two checks that are in Fortran to
765766
// prevent the callee from changing the type or to avoid having
766767
// to use a descriptor.
767768
if (!typesCompatible) {
@@ -770,7 +771,9 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
770771
(actualIsAllocatable && dummyIsAllocatable)) {
771772
bool actualIsUnlimited{actualType.type().IsUnlimitedPolymorphic()};
772773
bool dummyIsUnlimited{dummy.type.type().IsUnlimitedPolymorphic()};
774+
bool checkTypeCompatibility{true};
773775
if (actualIsUnlimited != dummyIsUnlimited) {
776+
checkTypeCompatibility = false;
774777
if (dummyIsUnlimited && dummy.intent == common::Intent::In &&
775778
context.IsEnabled(common::LanguageFeature::RelaxedIntentInChecking)) {
776779
if (context.ShouldWarn(
@@ -790,11 +793,21 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
790793
messages.Say(
791794
"If a POINTER or ALLOCATABLE dummy or actual argument is polymorphic, both should be so"_port_en_US);
792795
}
796+
} else if (actualIsPolymorphic &&
797+
context.IsEnabled(common::LanguageFeature::
798+
PolymorphicActualAllocatableOrPointerToMonomorphicDummy)) {
799+
if (context.ShouldWarn(common::LanguageFeature::
800+
PolymorphicActualAllocatableOrPointerToMonomorphicDummy)) {
801+
messages.Say(
802+
"If a POINTER or ALLOCATABLE actual argument is polymorphic, the corresponding dummy argument should also be so"_port_en_US);
803+
}
793804
} else {
805+
checkTypeCompatibility = false;
794806
messages.Say(
795807
"If a POINTER or ALLOCATABLE dummy or actual argument is polymorphic, both must be so"_err_en_US);
796808
}
797-
} else if (!actualIsUnlimited) {
809+
}
810+
if (checkTypeCompatibility && !actualIsUnlimited) {
798811
if (!actualType.type().IsTkCompatibleWith(dummy.type.type())) {
799812
if (dummy.intent == common::Intent::In &&
800813
context.IsEnabled(

flang/test/Semantics/call05.f90

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
! RUN: %python %S/test_errors.py %s %flang_fc1
1+
! RUN: %python %S/test_errors.py %s %flang_fc1 -pedantic
22
! Test 15.5.2.5 constraints and restrictions for POINTER & ALLOCATABLE
33
! arguments when both sides of the call have the same attributes.
44

@@ -73,9 +73,9 @@ subroutine test
7373
call sma(ma) ! ok
7474
call spp(pp) ! ok
7575
call spa(pa) ! ok
76-
!ERROR: If a POINTER or ALLOCATABLE dummy or actual argument is polymorphic, both must be so
76+
!PORTABILITY: If a POINTER or ALLOCATABLE actual argument is polymorphic, the corresponding dummy argument should also be so
7777
call smp(pp)
78-
!ERROR: If a POINTER or ALLOCATABLE dummy or actual argument is polymorphic, both must be so
78+
!PORTABILITY: If a POINTER or ALLOCATABLE actual argument is polymorphic, the corresponding dummy argument should also be so
7979
call sma(pa)
8080
!ERROR: If a POINTER or ALLOCATABLE dummy or actual argument is polymorphic, both must be so
8181
call spp(mp)

0 commit comments

Comments
 (0)