Skip to content

[flang] Extension: accept NULL([MOLD=]) for ALLOCATABLE INTENT(IN) du… #66256

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions flang/docs/Extensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,8 @@ end
* Unrestricted `INTRINSIC` functions are accepted for use in
`PROCEDURE` statements in generic interfaces, as in some other
compilers.
* A `NULL()` pointer is treated as an unallocated allocatable
when associated with an `INTENT(IN)` allocatable dummy argument.

### Extensions supported when enabled by options

Expand Down
2 changes: 1 addition & 1 deletion flang/include/flang/Common/Fortran-features.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ ENUM_CLASS(LanguageFeature, BackslashEscapes, OldDebugLines,
DistinguishableSpecifics, DefaultSave, PointerInSeqType, NonCharacterFormat,
SaveMainProgram, SaveBigMainProgramVariables,
DistinctArrayConstructorLengths, PPCVector, RelaxedIntentInChecking,
ForwardRefImplicitNoneData)
ForwardRefImplicitNoneData, NullActualForAllocatable)

// Portability and suspicious usage warnings for conforming code
ENUM_CLASS(UsageWarning, Portability, PointerToUndefinable,
Expand Down
53 changes: 39 additions & 14 deletions flang/lib/Semantics/check-call.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -661,17 +661,34 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
dummy.attrs.test(characteristics::DummyDataObject::Attr::Optional)};
bool actualIsNull{evaluate::IsNullPointer(actual)};
if (dummyIsAllocatable) {
if (!actualIsAllocatable && !(actualIsNull && dummyIsOptional)) {
if (actualIsAllocatable) {
if (actualIsCoindexed && dummy.intent != common::Intent::In) {
messages.Say(
"ALLOCATABLE %s must have INTENT(IN) to be associated with a coindexed actual argument"_err_en_US,
dummyName);
}
} else if (actualIsNull) {
if (dummyIsOptional) {
} else if (dummy.intent == common::Intent::In) {
// Extension (Intel, NAG, XLF): a NULL() pointer is an acceptable
// actual argument for an INTENT(IN) allocatable dummy, and it
// is treated as an unassociated allocatable.
if (context.languageFeatures().ShouldWarn(
common::LanguageFeature::NullActualForAllocatable)) {
messages.Say(
"Allocatable %s is associated with a null pointer"_port_en_US,
dummyName);
}
} else {
messages.Say(
"A null pointer may not be associated with allocatable %s without INTENT(IN)"_err_en_US,
dummyName);
}
} else {
messages.Say(
"ALLOCATABLE %s must be associated with an ALLOCATABLE actual argument"_err_en_US,
dummyName);
}
if (actualIsAllocatable && actualIsCoindexed &&
dummy.intent != common::Intent::In) {
messages.Say(
"ALLOCATABLE %s must have INTENT(IN) to be associated with a coindexed actual argument"_err_en_US,
dummyName);
}
if (!actualIsCoindexed && actualLastSymbol &&
actualLastSymbol->Corank() != dummy.type.corank()) {
messages.Say(
Expand Down Expand Up @@ -791,7 +808,8 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
}

// NULL(MOLD=) checking for non-intrinsic procedures
if (!intrinsic && !dummyIsPointer && !dummyIsOptional && actualIsNull) {
if (!intrinsic && !dummyIsAllocatableOrPointer && !dummyIsOptional &&
actualIsNull) {
messages.Say(
"Actual argument associated with %s may not be null pointer %s"_err_en_US,
dummyName, actual.AsFortran());
Expand Down Expand Up @@ -1083,12 +1101,19 @@ static void CheckExplicitInterfaceArg(evaluate::ActualArgument &arg,
} else if (object.attrs.test(characteristics::DummyDataObject::
Attr::Allocatable) &&
evaluate::IsNullPointer(*expr)) {
// Unsupported extension that more or less naturally falls
// out of other Fortran implementations that pass separate
// base address and descriptor address physical arguments
messages.Say(
"Null actual argument '%s' may not be associated with allocatable %s"_err_en_US,
expr->AsFortran(), dummyName);
if (object.intent == common::Intent::In) {
// Extension (Intel, NAG, XLF); see CheckExplicitDataArg.
if (context.languageFeatures().ShouldWarn(common::
LanguageFeature::NullActualForAllocatable)) {
messages.Say(
"Allocatable %s is associated with NULL()"_port_en_US,
dummyName);
}
} else {
messages.Say(
"NULL() actual argument '%s' may not be associated with allocatable %s without INTENT(IN)"_err_en_US,
expr->AsFortran(), dummyName);
}
} else {
messages.Say(
"Actual argument '%s' associated with %s is not a variable or typed expression"_err_en_US,
Expand Down
8 changes: 4 additions & 4 deletions flang/test/Semantics/call27.f90
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
! RUN: %python %S/test_errors.py %s %flang_fc1
! RUN: %python %S/test_errors.py %s %flang_fc1 -pedantic
! Catch NULL() actual argument association with allocatable dummy argument
program test
!ERROR: Null actual argument 'NULL()' may not be associated with allocatable dummy argument 'a='
!ERROR: NULL() actual argument 'NULL()' may not be associated with allocatable dummy argument 'a=' without INTENT(IN)
call foo1(null())
!ERROR: Null actual argument 'NULL()' may not be associated with allocatable dummy argument 'a='
call foo2(null()) ! perhaps permissible later on user request
!PORTABILITY: Allocatable dummy argument 'a=' is associated with NULL()
call foo2(null())
call foo3(null()) ! ok
contains
subroutine foo1(a)
Expand Down