[flang] More checking of NULL pointer actual arguments
Catch additional missing error cases for typed and untyped
NULL actual arguments to non-intrinsic procedures in cases
of explicit and implicit interfaces.
Differential Revision: https://reviews.llvm.org/D110003
GitOrigin-RevId: bcb2591b6ca00365cb9f99efafeb3bfe8682f002
diff --git a/lib/Semantics/check-call.cpp b/lib/Semantics/check-call.cpp
index b0c8fcd..e6a8434 100644
--- a/lib/Semantics/check-call.cpp
+++ b/lib/Semantics/check-call.cpp
@@ -48,8 +48,10 @@
if (const auto *expr{arg.UnwrapExpr()}) {
if (IsBOZLiteral(*expr)) {
messages.Say("BOZ argument requires an explicit interface"_err_en_US);
- }
- if (auto named{evaluate::ExtractNamedEntity(*expr)}) {
+ } else if (evaluate::IsNullPointer(*expr)) {
+ messages.Say(
+ "Null pointer argument requires an explicit interface"_err_en_US);
+ } else if (auto named{evaluate::ExtractNamedEntity(*expr)}) {
const Symbol &symbol{named->GetLastSymbol()};
if (symbol.Corank() > 0) {
messages.Say(
@@ -499,6 +501,16 @@
}
}
}
+
+ // NULL(MOLD=) checking for non-intrinsic procedures
+ bool dummyIsOptional{
+ dummy.attrs.test(characteristics::DummyDataObject::Attr::Optional)};
+ bool actualIsNull{evaluate::IsNullPointer(actual)};
+ if (!intrinsic && !dummyIsPointer && !dummyIsOptional && actualIsNull) {
+ messages.Say(
+ "Actual argument associated with %s may not be null pointer %s"_err_en_US,
+ dummyName, actual.AsFortran());
+ }
}
static void CheckProcedureArg(evaluate::ActualArgument &arg,
@@ -641,8 +653,10 @@
} else if (object.type.type().IsTypelessIntrinsicArgument() &&
evaluate::IsNullPointer(*expr)) {
// ok, ASSOCIATED(NULL())
- } else if (object.attrs.test(
- characteristics::DummyDataObject::Attr::Pointer) &&
+ } else if ((object.attrs.test(characteristics::DummyDataObject::
+ Attr::Pointer) ||
+ object.attrs.test(characteristics::
+ DummyDataObject::Attr::Optional)) &&
evaluate::IsNullPointer(*expr)) {
// ok, FOO(NULL())
} else {
diff --git a/lib/Semantics/pointer-assignment.cpp b/lib/Semantics/pointer-assignment.cpp
index afa1552..7003242 100644
--- a/lib/Semantics/pointer-assignment.cpp
+++ b/lib/Semantics/pointer-assignment.cpp
@@ -174,8 +174,7 @@
if (!lhsType_->IsCompatibleWith(context_.messages(), *frTypeAndShape,
"pointer", "function result", false /*elemental*/,
evaluate::CheckConformanceFlags::BothDeferredShape)) {
- msg = "%s is associated with the result of a reference to function '%s'"
- " whose pointer result has an incompatible type or shape"_err_en_US;
+ return false; // IsCompatibleWith() emitted message
}
}
if (msg) {
diff --git a/test/Semantics/null01.f90 b/test/Semantics/null01.f90
index 73ee760..8c89a0b 100644
--- a/test/Semantics/null01.f90
+++ b/test/Semantics/null01.f90
@@ -8,6 +8,10 @@
subroutine s1(j)
integer, intent(in) :: j
end subroutine
+ subroutine canbenull(x, y)
+ integer, intent(in), optional :: x
+ real, intent(in), pointer :: y
+ end
function f0()
real :: f0
end function
@@ -25,6 +29,7 @@
procedure(s1), pointer :: f3
end function
end interface
+ external implicit
type :: dt0
integer, pointer :: ip0
end type dt0
@@ -62,10 +67,8 @@
dt0x = dt0(ip0=null(ip0))
dt0x = dt0(ip0=null(mold=ip0))
!ERROR: function result type 'REAL(4)' is not compatible with pointer type 'INTEGER(4)'
- !ERROR: pointer 'ip0' is associated with the result of a reference to function 'null' whose pointer result has an incompatible type or shape
dt0x = dt0(ip0=null(mold=rp0))
!ERROR: function result type 'REAL(4)' is not compatible with pointer type 'INTEGER(4)'
- !ERROR: pointer 'ip1' is associated with the result of a reference to function 'null' whose pointer result has an incompatible type or shape
dt1x = dt1(ip1=null(mold=rp1))
dt2x = dt2(pps0=null())
dt2x = dt2(pps0=null(mold=dt2x%pps0))
@@ -74,4 +77,10 @@
!ERROR: Procedure pointer 'pps1' associated with result of reference to function 'null' that is an incompatible procedure pointer
dt3x = dt3(pps1=null(mold=dt2x%pps0))
dt3x = dt3(pps1=null(mold=dt3x%pps1))
+ call canbenull(null(), null()) ! fine
+ call canbenull(null(mold=ip0), null(mold=rp0)) ! fine
+ !ERROR: Null pointer argument requires an explicit interface
+ call implicit(null())
+ !ERROR: Null pointer argument requires an explicit interface
+ call implicit(null(mold=ip0))
end subroutine test