Skip to content

Commit 61d361d

Browse files
authored
[flang] Extension: accept NULL([MOLD=]) for ALLOCATABLE INTENT(IN) du… (llvm#66256)
…mmy argument Several compilers accept a null pointer (with or without a MOLD=) as an actual argument for association with an INTENT(IN) allocatable dummy argument. At runtime, the allocatable dummy argument appears to be in the unallocated state. This seems useful, unambiguous, unlikely to invalidate conforming code, and works with Intel, NAG, & XLF, so it should be supported with an optional portability warning in this compiler as well.
1 parent f286141 commit 61d361d

File tree

4 files changed

+46
-19
lines changed

4 files changed

+46
-19
lines changed

flang/docs/Extensions.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,8 @@ end
298298
* Unrestricted `INTRINSIC` functions are accepted for use in
299299
`PROCEDURE` statements in generic interfaces, as in some other
300300
compilers.
301+
* A `NULL()` pointer is treated as an unallocated allocatable
302+
when associated with an `INTENT(IN)` allocatable dummy argument.
301303

302304
### Extensions supported when enabled by options
303305

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ ENUM_CLASS(LanguageFeature, BackslashEscapes, OldDebugLines,
3737
DistinguishableSpecifics, DefaultSave, PointerInSeqType, NonCharacterFormat,
3838
SaveMainProgram, SaveBigMainProgramVariables,
3939
DistinctArrayConstructorLengths, PPCVector, RelaxedIntentInChecking,
40-
ForwardRefImplicitNoneData)
40+
ForwardRefImplicitNoneData, NullActualForAllocatable)
4141

4242
// Portability and suspicious usage warnings for conforming code
4343
ENUM_CLASS(UsageWarning, Portability, PointerToUndefinable,

flang/lib/Semantics/check-call.cpp

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -661,17 +661,34 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
661661
dummy.attrs.test(characteristics::DummyDataObject::Attr::Optional)};
662662
bool actualIsNull{evaluate::IsNullPointer(actual)};
663663
if (dummyIsAllocatable) {
664-
if (!actualIsAllocatable && !(actualIsNull && dummyIsOptional)) {
664+
if (actualIsAllocatable) {
665+
if (actualIsCoindexed && dummy.intent != common::Intent::In) {
666+
messages.Say(
667+
"ALLOCATABLE %s must have INTENT(IN) to be associated with a coindexed actual argument"_err_en_US,
668+
dummyName);
669+
}
670+
} else if (actualIsNull) {
671+
if (dummyIsOptional) {
672+
} else if (dummy.intent == common::Intent::In) {
673+
// Extension (Intel, NAG, XLF): a NULL() pointer is an acceptable
674+
// actual argument for an INTENT(IN) allocatable dummy, and it
675+
// is treated as an unassociated allocatable.
676+
if (context.languageFeatures().ShouldWarn(
677+
common::LanguageFeature::NullActualForAllocatable)) {
678+
messages.Say(
679+
"Allocatable %s is associated with a null pointer"_port_en_US,
680+
dummyName);
681+
}
682+
} else {
683+
messages.Say(
684+
"A null pointer may not be associated with allocatable %s without INTENT(IN)"_err_en_US,
685+
dummyName);
686+
}
687+
} else {
665688
messages.Say(
666689
"ALLOCATABLE %s must be associated with an ALLOCATABLE actual argument"_err_en_US,
667690
dummyName);
668691
}
669-
if (actualIsAllocatable && actualIsCoindexed &&
670-
dummy.intent != common::Intent::In) {
671-
messages.Say(
672-
"ALLOCATABLE %s must have INTENT(IN) to be associated with a coindexed actual argument"_err_en_US,
673-
dummyName);
674-
}
675692
if (!actualIsCoindexed && actualLastSymbol &&
676693
actualLastSymbol->Corank() != dummy.type.corank()) {
677694
messages.Say(
@@ -791,7 +808,8 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
791808
}
792809

793810
// NULL(MOLD=) checking for non-intrinsic procedures
794-
if (!intrinsic && !dummyIsPointer && !dummyIsOptional && actualIsNull) {
811+
if (!intrinsic && !dummyIsAllocatableOrPointer && !dummyIsOptional &&
812+
actualIsNull) {
795813
messages.Say(
796814
"Actual argument associated with %s may not be null pointer %s"_err_en_US,
797815
dummyName, actual.AsFortran());
@@ -1083,12 +1101,19 @@ static void CheckExplicitInterfaceArg(evaluate::ActualArgument &arg,
10831101
} else if (object.attrs.test(characteristics::DummyDataObject::
10841102
Attr::Allocatable) &&
10851103
evaluate::IsNullPointer(*expr)) {
1086-
// Unsupported extension that more or less naturally falls
1087-
// out of other Fortran implementations that pass separate
1088-
// base address and descriptor address physical arguments
1089-
messages.Say(
1090-
"Null actual argument '%s' may not be associated with allocatable %s"_err_en_US,
1091-
expr->AsFortran(), dummyName);
1104+
if (object.intent == common::Intent::In) {
1105+
// Extension (Intel, NAG, XLF); see CheckExplicitDataArg.
1106+
if (context.languageFeatures().ShouldWarn(common::
1107+
LanguageFeature::NullActualForAllocatable)) {
1108+
messages.Say(
1109+
"Allocatable %s is associated with NULL()"_port_en_US,
1110+
dummyName);
1111+
}
1112+
} else {
1113+
messages.Say(
1114+
"NULL() actual argument '%s' may not be associated with allocatable %s without INTENT(IN)"_err_en_US,
1115+
expr->AsFortran(), dummyName);
1116+
}
10921117
} else {
10931118
messages.Say(
10941119
"Actual argument '%s' associated with %s is not a variable or typed expression"_err_en_US,

flang/test/Semantics/call27.f90

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
! RUN: %python %S/test_errors.py %s %flang_fc1
1+
! RUN: %python %S/test_errors.py %s %flang_fc1 -pedantic
22
! Catch NULL() actual argument association with allocatable dummy argument
33
program test
4-
!ERROR: Null actual argument 'NULL()' may not be associated with allocatable dummy argument 'a='
4+
!ERROR: NULL() actual argument 'NULL()' may not be associated with allocatable dummy argument 'a=' without INTENT(IN)
55
call foo1(null())
6-
!ERROR: Null actual argument 'NULL()' may not be associated with allocatable dummy argument 'a='
7-
call foo2(null()) ! perhaps permissible later on user request
6+
!PORTABILITY: Allocatable dummy argument 'a=' is associated with NULL()
7+
call foo2(null())
88
call foo3(null()) ! ok
99
contains
1010
subroutine foo1(a)

0 commit comments

Comments
 (0)