[flang-commits] [flang] [flang] Implement check for statement function dummy argument names (PR #204417)
via flang-commits
flang-commits at lists.llvm.org
Thu Jun 18 07:40:03 PDT 2026
https://github.com/kwyatt-ext updated https://github.com/llvm/llvm-project/pull/204417
>From e0742f7e798ce223d44c6ae08951d30a5520618e Mon Sep 17 00:00:00 2001
From: Kevin Wyatt <kwyatt at hpe.com>
Date: Wed, 17 Jun 2026 14:12:53 -0500
Subject: [PATCH] Added check to prevent re-use of identifiers in statement
function dummy args.
---
flang/lib/Semantics/resolve-names.cpp | 18 ++++++++
flang/test/Semantics/bug121973.f90 | 1 +
flang/test/Semantics/stmt-func04.f90 | 66 +++++++++++++++++++++++++++
3 files changed, 85 insertions(+)
create mode 100644 flang/test/Semantics/stmt-func04.f90
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index 6d2d0bf24b194..60bdb98046bad 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -10451,6 +10451,24 @@ void ResolveNamesVisitor::AnalyzeStmtFunctionStmt(
details->moduleInterface() || symbol->test(Symbol::Flag::Subroutine)) {
return; // error recovery
}
+
+ // F2023 19.4 p2: a statement-function dummy argument name may be the same
+ // as an accessible name only if that name is a scalar variable. The lookup
+ // walks the host chain (but not into the global scope), so host-associated
+ // identifiers are also considered.
+ for (const auto &dummyName : std::get<std::list<parser::Name>>(stmtFunc.t)) {
+ if (const Symbol *hostSymbol{currScope().FindSymbol(dummyName.source)}) {
+ const Symbol &ultimate{hostSymbol->GetUltimate()};
+ const bool isScalarVariable{(ultimate.has<ObjectEntityDetails>() ||
+ ultimate.has<EntityDetails>()) &&
+ !IsNamedConstant(ultimate) && ultimate.Rank() == 0};
+ if (!isScalarVariable) {
+ Say(dummyName.source,
+ "The name '%s' of a statement function dummy argument may not be the same as an accessible name unless that name is a scalar variable"_err_en_US);
+ }
+ }
+ }
+
// Resolve the symbols on the RHS of the statement function.
PushScope(*symbol->scope());
const auto &parsedExpr{std::get<parser::Scalar<parser::Expr>>(stmtFunc.t)};
diff --git a/flang/test/Semantics/bug121973.f90 b/flang/test/Semantics/bug121973.f90
index 0ae04c808e416..2ec2260aeb557 100644
--- a/flang/test/Semantics/bug121973.f90
+++ b/flang/test/Semantics/bug121973.f90
@@ -3,6 +3,7 @@ subroutine s()
real(8) :: a
!ERROR: COMPLEX(KIND=128) is not a supported type
complex(128) :: x
+ !ERROR: The name 'i' of a statement function dummy argument may not be the same as an accessible name unless that name is a scalar variable
a(i)=a + ((i)+1) + 3.14
!ERROR: 'a' has not been declared as an array or pointer-valued function
a()=z(a * a + n-1 - x) + i((/0,0,0,0,0,0,0,0,0,0/)) + 8
diff --git a/flang/test/Semantics/stmt-func04.f90 b/flang/test/Semantics/stmt-func04.f90
new file mode 100644
index 0000000000000..f216fbd6912c4
--- /dev/null
+++ b/flang/test/Semantics/stmt-func04.f90
@@ -0,0 +1,66 @@
+! RUN: %python %S/test_errors.py %s %flang_fc1
+! F2023 19.4 p2: a statement function dummy argument name may be the same as an
+! accessible global identifier or local identifier of class (1) only if that
+! name is a scalar variable.
+
+! Clashes within the statement function's own scoping unit.
+subroutine local_clashes
+ real, external :: extf ! external procedure
+ real, parameter :: namedc = 1.0
+ real :: arr(10) ! array
+ type t; end type ! derived type
+ real :: scalarvar ! scalar variable (legal to shadow)
+
+ !ERROR: The name 'extf' of a statement function dummy argument may not be the same as an accessible name unless that name is a scalar variable
+ f1(extf) = extf + 1
+ !ERROR: The name 'namedc' of a statement function dummy argument may not be the same as an accessible name unless that name is a scalar variable
+ f2(namedc) = namedc + 1
+ !ERROR: The name 'arr' of a statement function dummy argument may not be the same as an accessible name unless that name is a scalar variable
+ f3(arr) = arr + 1
+ !ERROR: The name 't' of a statement function dummy argument may not be the same as an accessible name unless that name is a scalar variable
+ f4(t) = 1
+ f5(scalarvar) = scalarvar + 1 ! ok: scalar variable shadowing is permitted
+end subroutine
+
+! Clashes with host-associated identifiers (module scope).
+module m
+ integer :: hostarr(10)
+ integer :: hostscalar
+ integer, parameter :: hostconst = 3
+contains
+ subroutine host_clashes
+ !ERROR: The name 'hostarr' of a statement function dummy argument may not be the same as an accessible name unless that name is a scalar variable
+ g1(hostarr) = hostarr + 1
+ !ERROR: The name 'hostconst' of a statement function dummy argument may not be the same as an accessible name unless that name is a scalar variable
+ g2(hostconst) = hostconst + 1
+ g3(hostscalar) = hostscalar + 1 ! ok: host scalar variable
+ end subroutine
+end module
+
+! Clashes with grandparent-associated identifiers (internal procedure).
+program p
+ integer :: grandarr(5)
+ integer :: grandscalar
+contains
+ subroutine grand_clashes
+ !ERROR: The name 'grandarr' of a statement function dummy argument may not be the same as an accessible name unless that name is a scalar variable
+ h1(grandarr) = grandarr + 1
+ h2(grandscalar) = grandscalar + 1 ! ok: grandparent scalar variable
+ end subroutine
+end program
+
+! Clashes with USE-associated identifiers.
+module m_used
+ integer :: usearr(10)
+ integer :: usescalar
+ integer, parameter :: useconst = 5
+end module
+subroutine use_clashes
+ use m_used
+ !ERROR: The name 'usearr' of a statement function dummy argument may not be the same as an accessible name unless that name is a scalar variable
+ k1(usearr) = usearr + 1
+ !ERROR: The name 'useconst' of a statement function dummy argument may not be the same as an accessible name unless that name is a scalar variable
+ k2(useconst) = useconst + 1
+ k3(usescalar) = usescalar + 1 ! ok: USE-associated scalar variable
+end subroutine
+
More information about the flang-commits
mailing list