Skip to content

Commit bd28a0a

Browse files
committed
[flang] Catch attempts to do anything with statement functions other than call them
A statement function in Fortran may be called, but it may not be the target of a procedure pointer or passed as an actual argument.
1 parent dbfa4a0 commit bd28a0a

File tree

4 files changed

+57
-7
lines changed

4 files changed

+57
-7
lines changed

flang/lib/Semantics/check-call.cpp

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -77,13 +77,21 @@ static void CheckImplicitInterfaceArg(evaluate::ActualArgument &arg,
7777
"actual argument", *expr, context)}) {
7878
const auto *argProcDesignator{
7979
std::get_if<evaluate::ProcedureDesignator>(&expr->u)};
80-
const auto *argProcSymbol{
81-
argProcDesignator ? argProcDesignator->GetSymbol() : nullptr};
82-
if (argProcSymbol && !argChars->IsTypelessIntrinsicDummy() &&
83-
argProcDesignator && argProcDesignator->IsElemental()) { // C1533
84-
evaluate::SayWithDeclaration(messages, *argProcSymbol,
85-
"Non-intrinsic ELEMENTAL procedure '%s' may not be passed as an actual argument"_err_en_US,
86-
argProcSymbol->name());
80+
if (const auto *argProcSymbol{
81+
argProcDesignator ? argProcDesignator->GetSymbol() : nullptr}) {
82+
if (!argChars->IsTypelessIntrinsicDummy() && argProcDesignator &&
83+
argProcDesignator->IsElemental()) { // C1533
84+
evaluate::SayWithDeclaration(messages, *argProcSymbol,
85+
"Non-intrinsic ELEMENTAL procedure '%s' may not be passed as an actual argument"_err_en_US,
86+
argProcSymbol->name());
87+
} else if (const auto *subp{argProcSymbol->GetUltimate()
88+
.detailsIf<SubprogramDetails>()}) {
89+
if (subp->stmtFunction()) {
90+
evaluate::SayWithDeclaration(messages, *argProcSymbol,
91+
"Statement function '%s' may not be passed as an actual argument"_err_en_US,
92+
argProcSymbol->name());
93+
}
94+
}
8795
}
8896
}
8997
}
@@ -574,6 +582,17 @@ static void CheckProcedureArg(evaluate::ActualArgument &arg,
574582
std::get_if<evaluate::ProcedureDesignator>(&expr->u)};
575583
const auto *argProcSymbol{
576584
argProcDesignator ? argProcDesignator->GetSymbol() : nullptr};
585+
if (argProcSymbol) {
586+
if (const auto *subp{
587+
argProcSymbol->GetUltimate().detailsIf<SubprogramDetails>()}) {
588+
if (subp->stmtFunction()) {
589+
evaluate::SayWithDeclaration(messages, *argProcSymbol,
590+
"Statement function '%s' may not be passed as an actual argument"_err_en_US,
591+
argProcSymbol->name());
592+
return;
593+
}
594+
}
595+
}
577596
if (auto argChars{characteristics::DummyArgument::FromActual(
578597
"actual argument", *expr, context)}) {
579598
if (!argChars->IsTypelessIntrinsicDummy()) {

flang/lib/Semantics/pointer-assignment.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,17 @@ bool PointerAssignmentChecker::Check(parser::CharBlock rhsName, bool isCall,
279279
}
280280

281281
bool PointerAssignmentChecker::Check(const evaluate::ProcedureDesignator &d) {
282+
if (const Symbol * symbol{d.GetSymbol()}) {
283+
if (const auto *subp{
284+
symbol->GetUltimate().detailsIf<SubprogramDetails>()}) {
285+
if (subp->stmtFunction()) {
286+
evaluate::SayWithDeclaration(context_.messages(), *symbol,
287+
"Statement function '%s' may not be the target of a pointer assignment"_err_en_US,
288+
symbol->name());
289+
return false;
290+
}
291+
}
292+
}
282293
if (auto chars{Procedure::Characterize(d, context_)}) {
283294
return Check(d.GetName(), false, &*chars, d.GetSpecificIntrinsic());
284295
} else {

flang/test/Semantics/assign03.f90

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,4 +314,11 @@ subroutine s13
314314
ptr => s_external
315315
call ptr
316316
end subroutine
317+
318+
subroutine s14
319+
procedure(real), pointer :: ptr
320+
sf(x) = x + 1.
321+
!ERROR: Statement function 'sf' may not be the target of a pointer assignment
322+
ptr => sf
323+
end subroutine
317324
end

flang/test/Semantics/call02.f90

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,19 @@ elemental integer function elem()
4343
end function
4444
end
4545

46+
subroutine s03
47+
interface
48+
subroutine sub1(p)
49+
procedure(real) :: p
50+
end subroutine
51+
end interface
52+
sf(x) = x + 1.
53+
!ERROR: Statement function 'sf' may not be passed as an actual argument
54+
call sub1(sf)
55+
!ERROR: Statement function 'sf' may not be passed as an actual argument
56+
call sub2(sf)
57+
end
58+
4659
module m01
4760
procedure(sin) :: elem01
4861
interface

0 commit comments

Comments
 (0)