[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
This commit is contained in:
parent
757384abff
commit
bcb2591b6c
|
@ -48,8 +48,10 @@ static void CheckImplicitInterfaceArg(
|
|||
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 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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 @@ static void CheckExplicitInterfaceArg(evaluate::ActualArgument &arg,
|
|||
} 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 {
|
||||
|
|
|
@ -174,8 +174,7 @@ bool PointerAssignmentChecker::Check(const evaluate::FunctionRef<T> &f) {
|
|||
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) {
|
||||
|
|
|
@ -8,6 +8,10 @@ subroutine test
|
|||
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 @@ subroutine test
|
|||
procedure(s1), pointer :: f3
|
||||
end function
|
||||
end interface
|
||||
external implicit
|
||||
type :: dt0
|
||||
integer, pointer :: ip0
|
||||
end type dt0
|
||||
|
@ -62,10 +67,8 @@ subroutine test
|
|||
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 @@ subroutine test
|
|||
!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
|
||||
|
|
Loading…
Reference in New Issue