Skip to content

Commit bcb2591

Browse files
committed
[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
1 parent 757384a commit bcb2591

File tree

3 files changed

+30
-8
lines changed

3 files changed

+30
-8
lines changed

flang/lib/Semantics/check-call.cpp

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,10 @@ static void CheckImplicitInterfaceArg(
4848
if (const auto *expr{arg.UnwrapExpr()}) {
4949
if (IsBOZLiteral(*expr)) {
5050
messages.Say("BOZ argument requires an explicit interface"_err_en_US);
51-
}
52-
if (auto named{evaluate::ExtractNamedEntity(*expr)}) {
51+
} else if (evaluate::IsNullPointer(*expr)) {
52+
messages.Say(
53+
"Null pointer argument requires an explicit interface"_err_en_US);
54+
} else if (auto named{evaluate::ExtractNamedEntity(*expr)}) {
5355
const Symbol &symbol{named->GetLastSymbol()};
5456
if (symbol.Corank() > 0) {
5557
messages.Say(
@@ -499,6 +501,16 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
499501
}
500502
}
501503
}
504+
505+
// NULL(MOLD=) checking for non-intrinsic procedures
506+
bool dummyIsOptional{
507+
dummy.attrs.test(characteristics::DummyDataObject::Attr::Optional)};
508+
bool actualIsNull{evaluate::IsNullPointer(actual)};
509+
if (!intrinsic && !dummyIsPointer && !dummyIsOptional && actualIsNull) {
510+
messages.Say(
511+
"Actual argument associated with %s may not be null pointer %s"_err_en_US,
512+
dummyName, actual.AsFortran());
513+
}
502514
}
503515

504516
static void CheckProcedureArg(evaluate::ActualArgument &arg,
@@ -641,8 +653,10 @@ static void CheckExplicitInterfaceArg(evaluate::ActualArgument &arg,
641653
} else if (object.type.type().IsTypelessIntrinsicArgument() &&
642654
evaluate::IsNullPointer(*expr)) {
643655
// ok, ASSOCIATED(NULL())
644-
} else if (object.attrs.test(
645-
characteristics::DummyDataObject::Attr::Pointer) &&
656+
} else if ((object.attrs.test(characteristics::DummyDataObject::
657+
Attr::Pointer) ||
658+
object.attrs.test(characteristics::
659+
DummyDataObject::Attr::Optional)) &&
646660
evaluate::IsNullPointer(*expr)) {
647661
// ok, FOO(NULL())
648662
} else {

flang/lib/Semantics/pointer-assignment.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,8 +174,7 @@ bool PointerAssignmentChecker::Check(const evaluate::FunctionRef<T> &f) {
174174
if (!lhsType_->IsCompatibleWith(context_.messages(), *frTypeAndShape,
175175
"pointer", "function result", false /*elemental*/,
176176
evaluate::CheckConformanceFlags::BothDeferredShape)) {
177-
msg = "%s is associated with the result of a reference to function '%s'"
178-
" whose pointer result has an incompatible type or shape"_err_en_US;
177+
return false; // IsCompatibleWith() emitted message
179178
}
180179
}
181180
if (msg) {

flang/test/Semantics/null01.f90

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ subroutine s0
88
subroutine s1(j)
99
integer, intent(in) :: j
1010
end subroutine
11+
subroutine canbenull(x, y)
12+
integer, intent(in), optional :: x
13+
real, intent(in), pointer :: y
14+
end
1115
function f0()
1216
real :: f0
1317
end function
@@ -25,6 +29,7 @@ function f3()
2529
procedure(s1), pointer :: f3
2630
end function
2731
end interface
32+
external implicit
2833
type :: dt0
2934
integer, pointer :: ip0
3035
end type dt0
@@ -62,10 +67,8 @@ function f3()
6267
dt0x = dt0(ip0=null(ip0))
6368
dt0x = dt0(ip0=null(mold=ip0))
6469
!ERROR: function result type 'REAL(4)' is not compatible with pointer type 'INTEGER(4)'
65-
!ERROR: pointer 'ip0' is associated with the result of a reference to function 'null' whose pointer result has an incompatible type or shape
6670
dt0x = dt0(ip0=null(mold=rp0))
6771
!ERROR: function result type 'REAL(4)' is not compatible with pointer type 'INTEGER(4)'
68-
!ERROR: pointer 'ip1' is associated with the result of a reference to function 'null' whose pointer result has an incompatible type or shape
6972
dt1x = dt1(ip1=null(mold=rp1))
7073
dt2x = dt2(pps0=null())
7174
dt2x = dt2(pps0=null(mold=dt2x%pps0))
@@ -74,4 +77,10 @@ function f3()
7477
!ERROR: Procedure pointer 'pps1' associated with result of reference to function 'null' that is an incompatible procedure pointer
7578
dt3x = dt3(pps1=null(mold=dt2x%pps0))
7679
dt3x = dt3(pps1=null(mold=dt3x%pps1))
80+
call canbenull(null(), null()) ! fine
81+
call canbenull(null(mold=ip0), null(mold=rp0)) ! fine
82+
!ERROR: Null pointer argument requires an explicit interface
83+
call implicit(null())
84+
!ERROR: Null pointer argument requires an explicit interface
85+
call implicit(null(mold=ip0))
7786
end subroutine test

0 commit comments

Comments
 (0)