Skip to content

Commit ea2c88f

Browse files
authored
[flang] Improve handling of NULL() arguments to intrinsics (#93866)
Some intrinsics (extends_type_of, same_type_as) can accept a NULL actual argument so long as it has a MOLD=. Some intrinsics that are marked in the intrinsics table as accepting a NULL actual argument already should only do so if it has a MOLD=. Distinguish table entries that accept a NULL() only with a MOLD= from the few others that allow a bare NULL() and update tests. Fixes #93845.
1 parent caa0a26 commit ea2c88f

File tree

3 files changed

+51
-30
lines changed

3 files changed

+51
-30
lines changed

flang/lib/Evaluate/intrinsics.cpp

Lines changed: 37 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,8 @@ ENUM_CLASS(Optionality, required,
225225
)
226226

227227
ENUM_CLASS(ArgFlag, none,
228-
canBeNull, // actual argument can be NULL()
228+
canBeNull, // actual argument can be NULL(with or without MOLD=)
229+
canBeMoldNull, // actual argument can be NULL(with MOLD=)
229230
defaultsToSameKind, // for MatchingDefaultKIND
230231
defaultsToSizeKind, // for SizeDefaultKIND
231232
defaultsToDefaultForResult, // for DefaultingKIND
@@ -368,7 +369,7 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
368369
DefaultLogical},
369370
{"bit_size",
370371
{{"i", SameInt, Rank::anyOrAssumedRank, Optionality::required,
371-
common::Intent::In, {ArgFlag::canBeNull}}},
372+
common::Intent::In, {ArgFlag::canBeMoldNull}}},
372373
SameInt, Rank::scalar, IntrinsicClass::inquiryFunction},
373374
{"ble",
374375
{{"i", AnyInt, Rank::elementalOrBOZ},
@@ -403,7 +404,7 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
403404
{"dble", {{"a", AnyNumeric, Rank::elementalOrBOZ}}, DoublePrecision},
404405
{"digits",
405406
{{"x", AnyIntOrReal, Rank::anyOrAssumedRank, Optionality::required,
406-
common::Intent::In, {ArgFlag::canBeNull}}},
407+
common::Intent::In, {ArgFlag::canBeMoldNull}}},
407408
DefaultInt, Rank::scalar, IntrinsicClass::inquiryFunction},
408409
{"dim", {{"x", OperandIntOrReal}, {"y", OperandIntOrReal}},
409410
OperandIntOrReal},
@@ -449,7 +450,7 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
449450
IntrinsicClass::transformationalFunction},
450451
{"epsilon",
451452
{{"x", SameReal, Rank::anyOrAssumedRank, Optionality::required,
452-
common::Intent::In, {ArgFlag::canBeNull}}},
453+
common::Intent::In, {ArgFlag::canBeMoldNull}}},
453454
SameReal, Rank::scalar, IntrinsicClass::inquiryFunction},
454455
{"erf", {{"x", SameReal}}, SameReal},
455456
{"erfc", {{"x", SameReal}}, SameReal},
@@ -463,8 +464,11 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
463464
{"exponent", {{"x", AnyReal}}, DefaultInt},
464465
{"exp", {{"x", SameFloating}}, SameFloating},
465466
{"extends_type_of",
466-
{{"a", ExtensibleDerived, Rank::anyOrAssumedRank},
467-
{"mold", ExtensibleDerived, Rank::anyOrAssumedRank}},
467+
{{"a", ExtensibleDerived, Rank::anyOrAssumedRank, Optionality::required,
468+
common::Intent::In, {ArgFlag::canBeMoldNull}},
469+
{"mold", ExtensibleDerived, Rank::anyOrAssumedRank,
470+
Optionality::required, common::Intent::In,
471+
{ArgFlag::canBeMoldNull}}},
468472
DefaultLogical, Rank::scalar, IntrinsicClass::inquiryFunction},
469473
{"failed_images", {OptionalTEAM, SizeDefaultKIND}, KINDInt, Rank::vector,
470474
IntrinsicClass::transformationalFunction},
@@ -512,7 +516,7 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
512516
{"getpid", {}, DefaultInt},
513517
{"huge",
514518
{{"x", SameIntOrReal, Rank::anyOrAssumedRank, Optionality::required,
515-
common::Intent::In, {ArgFlag::canBeNull}}},
519+
common::Intent::In, {ArgFlag::canBeMoldNull}}},
516520
SameIntOrReal, Rank::scalar, IntrinsicClass::inquiryFunction},
517521
{"hypot", {{"x", OperandReal}, {"y", OperandReal}}, OperandReal},
518522
{"iachar", {{"c", AnyChar}, DefaultingKIND}, KINDInt},
@@ -574,7 +578,7 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
574578
{"jzext", {{"i", AnyInt}}, DefaultInt},
575579
{"kind",
576580
{{"x", AnyIntrinsic, Rank::elemental, Optionality::required,
577-
common::Intent::In, {ArgFlag::canBeNull}}},
581+
common::Intent::In, {ArgFlag::canBeMoldNull}}},
578582
DefaultInt, Rank::elemental, IntrinsicClass::inquiryFunction},
579583
{"lbound",
580584
{{"array", AnyData, Rank::anyOrAssumedRank}, RequiredDIM,
@@ -588,7 +592,7 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
588592
{"leadz", {{"i", AnyInt}}, DefaultInt},
589593
{"len",
590594
{{"string", AnyChar, Rank::anyOrAssumedRank, Optionality::required,
591-
common::Intent::In, {ArgFlag::canBeNull}},
595+
common::Intent::In, {ArgFlag::canBeMoldNull}},
592596
DefaultingKIND},
593597
KINDInt, Rank::scalar, IntrinsicClass::inquiryFunction},
594598
{"len_trim", {{"string", AnyChar}, DefaultingKIND}, KINDInt},
@@ -642,7 +646,7 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
642646
SameCharNoLen},
643647
{"maxexponent",
644648
{{"x", AnyReal, Rank::anyOrAssumedRank, Optionality::required,
645-
common::Intent::In, {ArgFlag::canBeNull}}},
649+
common::Intent::In, {ArgFlag::canBeMoldNull}}},
646650
DefaultInt, Rank::scalar, IntrinsicClass::inquiryFunction},
647651
{"maxloc",
648652
{{"array", AnyRelatable, Rank::array}, RequiredDIM, OptionalMASK,
@@ -681,7 +685,7 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
681685
SameCharNoLen},
682686
{"minexponent",
683687
{{"x", AnyReal, Rank::anyOrAssumedRank, Optionality::required,
684-
common::Intent::In, {ArgFlag::canBeNull}}},
688+
common::Intent::In, {ArgFlag::canBeMoldNull}}},
685689
DefaultInt, Rank::scalar, IntrinsicClass::inquiryFunction},
686690
{"minloc",
687691
{{"array", AnyRelatable, Rank::array}, RequiredDIM, OptionalMASK,
@@ -707,7 +711,7 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
707711
{"nearest", {{"x", SameReal}, {"s", AnyReal}}, SameReal},
708712
{"new_line",
709713
{{"a", SameCharNoLen, Rank::anyOrAssumedRank, Optionality::required,
710-
common::Intent::In, {ArgFlag::canBeNull}}},
714+
common::Intent::In, {ArgFlag::canBeMoldNull}}},
711715
SameCharNoLen, Rank::scalar, IntrinsicClass::inquiryFunction},
712716
{"nint", {{"a", AnyReal}, DefaultingKIND}, KINDInt},
713717
{"norm2", {{"x", SameReal, Rank::array}, RequiredDIM}, SameReal,
@@ -747,21 +751,21 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
747751
SameNumeric, Rank::scalar, IntrinsicClass::transformationalFunction},
748752
{"precision",
749753
{{"x", AnyFloating, Rank::anyOrAssumedRank, Optionality::required,
750-
common::Intent::In, {ArgFlag::canBeNull}}},
754+
common::Intent::In, {ArgFlag::canBeMoldNull}}},
751755
DefaultInt, Rank::scalar, IntrinsicClass::inquiryFunction},
752756
{"present", {{"a", Addressable, Rank::anyOrAssumedRank}}, DefaultLogical,
753757
Rank::scalar, IntrinsicClass::inquiryFunction},
754758
{"radix",
755759
{{"x", AnyIntOrReal, Rank::anyOrAssumedRank, Optionality::required,
756-
common::Intent::In, {ArgFlag::canBeNull}}},
760+
common::Intent::In, {ArgFlag::canBeMoldNull}}},
757761
DefaultInt, Rank::scalar, IntrinsicClass::inquiryFunction},
758762
{"range",
759763
{{"x", AnyNumeric, Rank::anyOrAssumedRank, Optionality::required,
760-
common::Intent::In, {ArgFlag::canBeNull}}},
764+
common::Intent::In, {ArgFlag::canBeMoldNull}}},
761765
DefaultInt, Rank::scalar, IntrinsicClass::inquiryFunction},
762766
{"rank",
763767
{{"a", AnyData, Rank::anyOrAssumedRank, Optionality::required,
764-
common::Intent::In, {ArgFlag::canBeNull}}},
768+
common::Intent::In, {ArgFlag::canBeMoldNull}}},
765769
DefaultInt, Rank::scalar, IntrinsicClass::inquiryFunction},
766770
{"real", {{"a", SameComplex, Rank::elemental}},
767771
SameReal}, // 16.9.160(4)(ii)
@@ -792,8 +796,11 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
792796
SameType, Rank::shaped, IntrinsicClass::transformationalFunction},
793797
{"rrspacing", {{"x", SameReal}}, SameReal},
794798
{"same_type_as",
795-
{{"a", ExtensibleDerived, Rank::anyOrAssumedRank},
796-
{"b", ExtensibleDerived, Rank::anyOrAssumedRank}},
799+
{{"a", ExtensibleDerived, Rank::anyOrAssumedRank, Optionality::required,
800+
common::Intent::In, {ArgFlag::canBeMoldNull}},
801+
{"b", ExtensibleDerived, Rank::anyOrAssumedRank,
802+
Optionality::required, common::Intent::In,
803+
{ArgFlag::canBeMoldNull}}},
797804
DefaultLogical, Rank::scalar, IntrinsicClass::inquiryFunction},
798805
{"scale", {{"x", SameReal}, {"i", AnyInt}}, SameReal}, // == IEEE_SCALB()
799806
{"scan",
@@ -851,7 +858,7 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
851858
IntrinsicClass::transformationalFunction},
852859
{"storage_size",
853860
{{"a", AnyData, Rank::anyOrAssumedRank, Optionality::required,
854-
common::Intent::In, {ArgFlag::canBeNull}},
861+
common::Intent::In, {ArgFlag::canBeMoldNull}},
855862
SizeDefaultKIND},
856863
KINDInt, Rank::scalar, IntrinsicClass::inquiryFunction},
857864
{"sum", {{"array", SameNumeric, Rank::array}, RequiredDIM, OptionalMASK},
@@ -873,7 +880,7 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
873880
IntrinsicClass::transformationalFunction},
874881
{"tiny",
875882
{{"x", SameReal, Rank::anyOrAssumedRank, Optionality::required,
876-
common::Intent::In, {ArgFlag::canBeNull}}},
883+
common::Intent::In, {ArgFlag::canBeMoldNull}}},
877884
SameReal, Rank::scalar, IntrinsicClass::inquiryFunction},
878885
{"trailz", {{"i", AnyInt}}, DefaultInt},
879886
{"transfer",
@@ -1744,9 +1751,11 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
17441751
return std::nullopt;
17451752
}
17461753
if (!d.flags.test(ArgFlag::canBeNull)) {
1747-
// NULL() is rarely an acceptable intrinsic argument.
1748-
if (const auto *expr{arg->UnwrapExpr()}) {
1749-
if (IsNullPointer(*expr)) {
1754+
if (const auto *expr{arg->UnwrapExpr()}; expr && IsNullPointer(*expr)) {
1755+
if (!IsBareNullPointer(expr) && IsNullObjectPointer(*expr) &&
1756+
d.flags.test(ArgFlag::canBeMoldNull)) {
1757+
// ok
1758+
} else {
17501759
messages.Say(arg->sourceLocation(),
17511760
"A NULL() pointer is not allowed for '%s=' intrinsic argument"_err_en_US,
17521761
d.keyword);
@@ -1801,19 +1810,18 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
18011810
}
18021811
}
18031812
} else {
1804-
// NULL(), procedure, or procedure pointer
1813+
// NULL(no MOLD=), procedure, or procedure pointer
18051814
CHECK(IsProcedurePointerTarget(expr));
18061815
if (d.typePattern.kindCode == KindCode::addressable ||
18071816
d.rank == Rank::reduceOperation) {
18081817
continue;
18091818
} else if (d.typePattern.kindCode == KindCode::nullPointerType) {
18101819
continue;
1811-
} else if (IsNullPointer(expr)) {
1812-
messages.Say(arg->sourceLocation(),
1813-
"Actual argument for '%s=' may not be NULL()"_err_en_US,
1814-
d.keyword);
1820+
} else if (IsBareNullPointer(&expr)) {
1821+
// checked elsewhere
1822+
continue;
18151823
} else {
1816-
CHECK(IsProcedure(expr));
1824+
CHECK(IsProcedure(expr) || IsProcedurePointer(expr));
18171825
messages.Say(arg->sourceLocation(),
18181826
"Actual argument for '%s=' may not be a procedure"_err_en_US,
18191827
d.keyword);

flang/test/Semantics/null01.f90

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ function f3()
4949
type :: dt4
5050
real, allocatable :: ra0
5151
end type dt4
52+
type, extends(dt4) :: dt5
53+
end type dt5
5254
integer :: j
5355
type(dt0) :: dt0x
5456
type(dt1) :: dt1x
@@ -64,6 +66,8 @@ function f3()
6466
integer, parameter :: eight = ip0r + ip1r + ip2r + 5
6567
real(kind=eight) :: r8check
6668
logical, pointer :: lp
69+
type(dt4), pointer :: dt4p
70+
type(dt5), pointer :: dt5p
6771
ip0 => null() ! ok
6872
ip0 => null(null()) ! ok
6973
ip0 => null(null(null())) ! ok
@@ -115,6 +119,15 @@ function f3()
115119
call implicit(null(mold=ip0))
116120
!ERROR: A NULL() pointer is not allowed for 'x=' intrinsic argument
117121
print *, sin(null(rp0))
122+
!ERROR: A NULL() pointer is not allowed for 'x=' intrinsic argument
123+
print *, kind(null())
124+
print *, kind(null(rp0)) ! ok
125+
!ERROR: A NULL() pointer is not allowed for 'a=' intrinsic argument
126+
print *, extends_type_of(null(), null())
127+
print *, extends_type_of(null(dt5p), null(dt4p)) ! ok
128+
!ERROR: A NULL() pointer is not allowed for 'a=' intrinsic argument
129+
print *, same_type_as(null(), null())
130+
print *, same_type_as(null(dt5p), null(dt4p)) ! ok
118131
!ERROR: A NULL() pointer is not allowed for 'source=' intrinsic argument
119132
print *, transfer(null(rp0),ip0)
120133
!WARNING: Source of TRANSFER contains allocatable or pointer component %ra0

flang/test/Semantics/resolve09.f90

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ subroutine s10
156156

157157
subroutine s11
158158
real, pointer :: p(:)
159-
!ERROR: Actual argument for 'a=' may not be NULL()
159+
!ERROR: A NULL() pointer is not allowed for 'a=' intrinsic argument
160160
print *, rank(null())
161161
print *, rank(null(mold=p)) ! ok
162162
end

0 commit comments

Comments
 (0)