[flang-commits] [flang] bd28a0a - [flang] Catch attempts to do anything with statement functions other than call them
Peter Klausler via flang-commits
flang-commits at lists.llvm.org
Sun Oct 30 17:54:32 PDT 2022
Author: Peter Klausler
Date: 2022-10-30T17:54:22-07:00
New Revision: bd28a0a51181ad33dc9030fb887d26cd6b238c1f
URL: https://github.com/llvm/llvm-project/commit/bd28a0a51181ad33dc9030fb887d26cd6b238c1f
DIFF: https://github.com/llvm/llvm-project/commit/bd28a0a51181ad33dc9030fb887d26cd6b238c1f.diff
LOG: [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.
Added:
Modified:
flang/lib/Semantics/check-call.cpp
flang/lib/Semantics/pointer-assignment.cpp
flang/test/Semantics/assign03.f90
flang/test/Semantics/call02.f90
Removed:
################################################################################
diff --git a/flang/lib/Semantics/check-call.cpp b/flang/lib/Semantics/check-call.cpp
index 418d66d3d5db..d36ddd3623ba 100644
--- a/flang/lib/Semantics/check-call.cpp
+++ b/flang/lib/Semantics/check-call.cpp
@@ -77,13 +77,21 @@ static void CheckImplicitInterfaceArg(evaluate::ActualArgument &arg,
"actual argument", *expr, context)}) {
const auto *argProcDesignator{
std::get_if<evaluate::ProcedureDesignator>(&expr->u)};
- const auto *argProcSymbol{
- argProcDesignator ? argProcDesignator->GetSymbol() : nullptr};
- if (argProcSymbol && !argChars->IsTypelessIntrinsicDummy() &&
- argProcDesignator && argProcDesignator->IsElemental()) { // C1533
- evaluate::SayWithDeclaration(messages, *argProcSymbol,
- "Non-intrinsic ELEMENTAL procedure '%s' may not be passed as an actual argument"_err_en_US,
- argProcSymbol->name());
+ if (const auto *argProcSymbol{
+ argProcDesignator ? argProcDesignator->GetSymbol() : nullptr}) {
+ if (!argChars->IsTypelessIntrinsicDummy() && argProcDesignator &&
+ argProcDesignator->IsElemental()) { // C1533
+ evaluate::SayWithDeclaration(messages, *argProcSymbol,
+ "Non-intrinsic ELEMENTAL procedure '%s' may not be passed as an actual argument"_err_en_US,
+ argProcSymbol->name());
+ } else if (const auto *subp{argProcSymbol->GetUltimate()
+ .detailsIf<SubprogramDetails>()}) {
+ if (subp->stmtFunction()) {
+ evaluate::SayWithDeclaration(messages, *argProcSymbol,
+ "Statement function '%s' may not be passed as an actual argument"_err_en_US,
+ argProcSymbol->name());
+ }
+ }
}
}
}
@@ -574,6 +582,17 @@ static void CheckProcedureArg(evaluate::ActualArgument &arg,
std::get_if<evaluate::ProcedureDesignator>(&expr->u)};
const auto *argProcSymbol{
argProcDesignator ? argProcDesignator->GetSymbol() : nullptr};
+ if (argProcSymbol) {
+ if (const auto *subp{
+ argProcSymbol->GetUltimate().detailsIf<SubprogramDetails>()}) {
+ if (subp->stmtFunction()) {
+ evaluate::SayWithDeclaration(messages, *argProcSymbol,
+ "Statement function '%s' may not be passed as an actual argument"_err_en_US,
+ argProcSymbol->name());
+ return;
+ }
+ }
+ }
if (auto argChars{characteristics::DummyArgument::FromActual(
"actual argument", *expr, context)}) {
if (!argChars->IsTypelessIntrinsicDummy()) {
diff --git a/flang/lib/Semantics/pointer-assignment.cpp b/flang/lib/Semantics/pointer-assignment.cpp
index 69e80e5a1240..54e36f5b085b 100644
--- a/flang/lib/Semantics/pointer-assignment.cpp
+++ b/flang/lib/Semantics/pointer-assignment.cpp
@@ -279,6 +279,17 @@ bool PointerAssignmentChecker::Check(parser::CharBlock rhsName, bool isCall,
}
bool PointerAssignmentChecker::Check(const evaluate::ProcedureDesignator &d) {
+ if (const Symbol * symbol{d.GetSymbol()}) {
+ if (const auto *subp{
+ symbol->GetUltimate().detailsIf<SubprogramDetails>()}) {
+ if (subp->stmtFunction()) {
+ evaluate::SayWithDeclaration(context_.messages(), *symbol,
+ "Statement function '%s' may not be the target of a pointer assignment"_err_en_US,
+ symbol->name());
+ return false;
+ }
+ }
+ }
if (auto chars{Procedure::Characterize(d, context_)}) {
return Check(d.GetName(), false, &*chars, d.GetSpecificIntrinsic());
} else {
diff --git a/flang/test/Semantics/assign03.f90 b/flang/test/Semantics/assign03.f90
index 5740339edb55..a5d12be48785 100644
--- a/flang/test/Semantics/assign03.f90
+++ b/flang/test/Semantics/assign03.f90
@@ -314,4 +314,11 @@ subroutine s13
ptr => s_external
call ptr
end subroutine
+
+ subroutine s14
+ procedure(real), pointer :: ptr
+ sf(x) = x + 1.
+ !ERROR: Statement function 'sf' may not be the target of a pointer assignment
+ ptr => sf
+ end subroutine
end
diff --git a/flang/test/Semantics/call02.f90 b/flang/test/Semantics/call02.f90
index 8ef10415be80..264a79f8983a 100644
--- a/flang/test/Semantics/call02.f90
+++ b/flang/test/Semantics/call02.f90
@@ -43,6 +43,19 @@ elemental integer function elem()
end function
end
+subroutine s03
+ interface
+ subroutine sub1(p)
+ procedure(real) :: p
+ end subroutine
+ end interface
+ sf(x) = x + 1.
+ !ERROR: Statement function 'sf' may not be passed as an actual argument
+ call sub1(sf)
+ !ERROR: Statement function 'sf' may not be passed as an actual argument
+ call sub2(sf)
+end
+
module m01
procedure(sin) :: elem01
interface
More information about the flang-commits
mailing list