Skip to content

Commit 9a20612

Browse files
authored
[flang] NULL(NULL(NULL(...(NULL()...))) means NULL() (#83738)
When the actual MOLD= argument of a reference to the intrinsic function NULL is itself just NULL() (possibly nested), treat the MOLD= as if it had not been present. Fixes #83572.
1 parent 17162b6 commit 9a20612

File tree

2 files changed

+33
-10
lines changed

2 files changed

+33
-10
lines changed

flang/lib/Evaluate/intrinsics.cpp

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2635,19 +2635,30 @@ SpecificCall IntrinsicProcTable::Implementation::HandleNull(
26352635
static const char *const keywords[]{"mold", nullptr};
26362636
if (CheckAndRearrangeArguments(arguments, context.messages(), keywords, 1) &&
26372637
arguments[0]) {
2638-
if (Expr<SomeType> * mold{arguments[0]->UnwrapExpr()}) {
2639-
bool isProcPtrTarget{IsProcedurePointerTarget(*mold)};
2638+
Expr<SomeType> *mold{arguments[0]->UnwrapExpr()};
2639+
bool isBareNull{IsBareNullPointer(mold)};
2640+
if (isBareNull) {
2641+
// NULL(NULL()), NULL(NULL(NULL())), &c. are all just NULL()
2642+
mold = nullptr;
2643+
}
2644+
if (mold) {
2645+
bool isProcPtrTarget{
2646+
IsProcedurePointerTarget(*mold) && !IsNullObjectPointer(*mold)};
26402647
if (isProcPtrTarget || IsAllocatableOrPointerObject(*mold)) {
26412648
characteristics::DummyArguments args;
26422649
std::optional<characteristics::FunctionResult> fResult;
26432650
if (isProcPtrTarget) {
26442651
// MOLD= procedure pointer
2645-
const Symbol *last{GetLastSymbol(*mold)};
2646-
CHECK(last);
2647-
auto procPointer{IsProcedure(*last)
2648-
? characteristics::Procedure::Characterize(*last, context)
2649-
: std::nullopt};
2650-
// procPointer is null if there was an error with the analysis
2652+
std::optional<characteristics::Procedure> procPointer;
2653+
if (IsNullProcedurePointer(*mold)) {
2654+
procPointer =
2655+
characteristics::Procedure::Characterize(*mold, context);
2656+
} else {
2657+
const Symbol *last{GetLastSymbol(*mold)};
2658+
procPointer =
2659+
characteristics::Procedure::Characterize(DEREF(last), context);
2660+
}
2661+
// procPointer is vacant if there was an error with the analysis
26512662
// associated with the procedure pointer
26522663
if (procPointer) {
26532664
args.emplace_back("mold"s,
@@ -2676,8 +2687,10 @@ SpecificCall IntrinsicProcTable::Implementation::HandleNull(
26762687
}
26772688
}
26782689
}
2679-
context.messages().Say(arguments[0]->sourceLocation(),
2680-
"MOLD= argument to NULL() must be a pointer or allocatable"_err_en_US);
2690+
if (!isBareNull) {
2691+
context.messages().Say(arguments[0]->sourceLocation(),
2692+
"MOLD= argument to NULL() must be a pointer or allocatable"_err_en_US);
2693+
}
26812694
}
26822695
characteristics::Procedure::Attrs attrs;
26832696
attrs.set(characteristics::Procedure::Attr::NullPointer);

flang/test/Semantics/null01.f90

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,22 @@ function f3()
6565
real(kind=eight) :: r8check
6666
logical, pointer :: lp
6767
ip0 => null() ! ok
68+
ip0 => null(null()) ! ok
69+
ip0 => null(null(null())) ! ok
6870
ip1 => null() ! ok
71+
ip1 => null(null()) ! ok
72+
ip1 => null(null(null())) ! ok
6973
ip2 => null() ! ok
74+
ip2 => null(null()) ! ok
75+
ip2 => null(null(null())) ! ok
7076
!ERROR: MOLD= argument to NULL() must be a pointer or allocatable
7177
ip0 => null(mold=1)
7278
!ERROR: MOLD= argument to NULL() must be a pointer or allocatable
79+
ip0 => null(null(mold=1))
80+
!ERROR: MOLD= argument to NULL() must be a pointer or allocatable
7381
ip0 => null(mold=j)
82+
!ERROR: MOLD= argument to NULL() must be a pointer or allocatable
83+
ip0 => null(mold=null(mold=j))
7484
dt0x = dt0(null())
7585
dt0x = dt0(ip0=null())
7686
dt0x = dt0(ip0=null(ip0))

0 commit comments

Comments
 (0)