Skip to content

Commit 9a49a03

Browse files
authored
[flang] Refine handling of NULL() actual to non-optional allocatable … (#116126)
…dummy We presently allow a NULL() actual argument to associate with a non-optional dummy allocatable argument only under INTENT(IN). This is too strict, as it precludes the case of a dummy argument with default intent. Continue to require that the actual argument be definable under INTENT(OUT) and INTENT(IN OUT), and (contra XLF) interpret NULL() as being an expression, not a definable variable, even when it is given an allocatable MOLD. Fixes #115984.
1 parent 4fcab8a commit 9a49a03

File tree

4 files changed

+47
-25
lines changed

4 files changed

+47
-25
lines changed

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ ENUM_CLASS(UsageWarning, Portability, PointerToUndefinable,
7474
IndexVarRedefinition, IncompatibleImplicitInterfaces,
7575
VectorSubscriptFinalization, UndefinedFunctionResult, UselessIomsg,
7676
MismatchingDummyProcedure, SubscriptedEmptyArray, UnsignedLiteralTruncation,
77-
CompatibleDeclarationsFromDistinctModules)
77+
CompatibleDeclarationsFromDistinctModules,
78+
NullActualForDefaultIntentAllocatable)
7879

7980
using LanguageFeatures = EnumSet<LanguageFeature, LanguageFeature_enumSize>;
8081
using UsageWarnings = EnumSet<UsageWarning, UsageWarning_enumSize>;

flang/lib/Semantics/check-call.cpp

+28-23
Original file line numberDiff line numberDiff line change
@@ -793,21 +793,21 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
793793
}
794794
} else if (actualIsNull) {
795795
if (dummyIsOptional) {
796-
} else if (dummy.intent == common::Intent::In) {
797-
// Extension (Intel, NAG, XLF): a NULL() pointer is an acceptable
798-
// actual argument for an INTENT(IN) allocatable dummy, and it
799-
// is treated as an unassociated allocatable.
800-
if (context.ShouldWarn(
801-
common::LanguageFeature::NullActualForAllocatable)) {
802-
messages.Say(common::LanguageFeature::NullActualForAllocatable,
803-
"Allocatable %s is associated with a null pointer"_port_en_US,
804-
dummyName);
805-
}
806-
} else {
796+
} else if (dummy.intent == common::Intent::Default &&
797+
context.ShouldWarn(
798+
common::UsageWarning::NullActualForDefaultIntentAllocatable)) {
807799
messages.Say(
808-
"A null pointer may not be associated with allocatable %s without INTENT(IN)"_err_en_US,
800+
"A null pointer should not be associated with allocatable %s without INTENT(IN)"_warn_en_US,
801+
dummyName);
802+
} else if (dummy.intent == common::Intent::In &&
803+
context.ShouldWarn(
804+
common::LanguageFeature::NullActualForAllocatable)) {
805+
messages.Say(common::LanguageFeature::NullActualForAllocatable,
806+
"Allocatable %s is associated with a null pointer"_port_en_US,
809807
dummyName);
810808
}
809+
// INTENT(OUT) and INTENT(IN OUT) cases are caught elsewhere as being
810+
// undefinable actual arguments.
811811
} else {
812812
messages.Say(
813813
"ALLOCATABLE %s must be associated with an ALLOCATABLE actual argument"_err_en_US,
@@ -1292,19 +1292,24 @@ static void CheckExplicitInterfaceArg(evaluate::ActualArgument &arg,
12921292
} else if (object.attrs.test(characteristics::DummyDataObject::
12931293
Attr::Allocatable) &&
12941294
evaluate::IsNullPointer(*expr)) {
1295-
if (object.intent == common::Intent::In) {
1296-
// Extension (Intel, NAG, XLF); see CheckExplicitDataArg.
1297-
if (context.ShouldWarn(common::LanguageFeature::
1298-
NullActualForAllocatable)) {
1299-
messages.Say(
1300-
common::LanguageFeature::NullActualForAllocatable,
1301-
"Allocatable %s is associated with NULL()"_port_en_US,
1302-
dummyName);
1303-
}
1304-
} else {
1295+
if (object.intent == common::Intent::Out ||
1296+
object.intent == common::Intent::InOut) {
13051297
messages.Say(
1306-
"NULL() actual argument '%s' may not be associated with allocatable %s without INTENT(IN)"_err_en_US,
1298+
"NULL() actual argument '%s' may not be associated with allocatable dummy argument %s that is INTENT(OUT) or INTENT(IN OUT)"_err_en_US,
13071299
expr->AsFortran(), dummyName);
1300+
} else if (object.intent == common::Intent::Default &&
1301+
context.ShouldWarn(common::UsageWarning::
1302+
NullActualForDefaultIntentAllocatable)) {
1303+
messages.Say(common::UsageWarning::
1304+
NullActualForDefaultIntentAllocatable,
1305+
"NULL() actual argument '%s' should not be associated with allocatable dummy argument %s without INTENT(IN)"_warn_en_US,
1306+
expr->AsFortran(), dummyName);
1307+
} else if (context.ShouldWarn(common::LanguageFeature::
1308+
NullActualForAllocatable)) {
1309+
messages.Say(
1310+
common::LanguageFeature::NullActualForAllocatable,
1311+
"Allocatable %s is associated with %s"_port_en_US,
1312+
dummyName, expr->AsFortran());
13081313
}
13091314
} else {
13101315
messages.Say(

flang/lib/Support/Fortran-features.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,10 @@ LanguageFeatureControl::LanguageFeatureControl() {
8484
warnUsage_.set(UsageWarning::UndefinedFunctionResult);
8585
warnUsage_.set(UsageWarning::UselessIomsg);
8686
warnUsage_.set(UsageWarning::UnsignedLiteralTruncation);
87+
warnUsage_.set(UsageWarning::NullActualForDefaultIntentAllocatable);
8788
// New warnings, on by default
8889
warnLanguage_.set(LanguageFeature::SavedLocalInSpecExpr);
90+
warnLanguage_.set(LanguageFeature::NullActualForAllocatable);
8991
}
9092

9193
// Ignore case and any inserted punctuation (like '-'/'_')

flang/test/Semantics/call27.f90

+15-1
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,26 @@
11
! 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=' without INTENT(IN)
4+
real, allocatable :: a
5+
!ERROR: NULL() actual argument 'NULL()' may not be associated with allocatable dummy argument dummy argument 'a=' that is INTENT(OUT) or INTENT(IN OUT)
6+
call foo0(null())
7+
!WARNING: NULL() actual argument 'NULL()' should not be associated with allocatable dummy argument dummy argument 'a=' without INTENT(IN)
58
call foo1(null())
69
!PORTABILITY: Allocatable dummy argument 'a=' is associated with NULL()
710
call foo2(null())
811
call foo3(null()) ! ok
12+
!ERROR: Actual argument associated with INTENT(IN OUT) dummy argument 'a=' is not definable
13+
!BECAUSE: 'null(mold=a)' is a null pointer
14+
call foo0(null(mold=a))
15+
!WARNING: A null pointer should not be associated with allocatable dummy argument 'a=' without INTENT(IN)
16+
call foo1(null(mold=a))
17+
!PORTABILITY: Allocatable dummy argument 'a=' is associated with a null pointer
18+
call foo2(null(mold=a))
19+
call foo3(null(mold=a)) ! ok
920
contains
21+
subroutine foo0(a)
22+
real, allocatable, intent(in out) :: a
23+
end subroutine
1024
subroutine foo1(a)
1125
real, allocatable :: a
1226
end subroutine

0 commit comments

Comments
 (0)