[flang-commits] [flang] [flang] Diagnose assumed-type statement function dummy arguments (PR #227694)
Shrisha Kumar via flang-commits
flang-commits at lists.llvm.org
Wed Oct 14 01:48:43 PDT 2026
https://github.com/Shrisha4real updated https://github.com/llvm/llvm-project/pull/227694
>From ea4b0ae72c777a510fdb31907d59b2952c481a60 Mon Sep 17 00:00:00 2001
From: shrikuma <Shrisha.Kumar at amd.com>
Date: Tue, 29 Sep 2026 20:49:50 +0530
Subject: [PATCH 1/2] [flang] Diagnose assumed-type statement function dummy
arguments
A statement function dummy argument takes its type and type parameters
from the same-named entity in the host scope (F2023 15.6.4). A TYPE(*)
entity has no declared type, so it cannot supply one. Flang copied the
assumed type into the dummy without checking, so an uncalled definition
was silently accepted and a call hit the assertion in
genStmtFunctionRef.
Report an error in HandleStmtFunction and do not copy the assumed type.
Update the stale TODO in ConvertCall.cpp.
Also warn under -pedantic (StatementFunctionExtensions) when the
CHARACTER length of a statement function result or dummy argument is not
a constant expression. This is a portability warning, not an error,
because gfortran and ifx accept it and existing Lower tests rely on it.
Add Semantics/stmt-func05.f90.
---
flang/lib/Lower/ConvertCall.cpp | 5 +-
flang/lib/Semantics/check-declarations.cpp | 22 +++++++++
flang/lib/Semantics/resolve-names.cpp | 8 +++-
flang/test/Semantics/stmt-func05.f90 | 56 ++++++++++++++++++++++
4 files changed, 87 insertions(+), 4 deletions(-)
create mode 100644 flang/test/Semantics/stmt-func05.f90
diff --git a/flang/lib/Lower/ConvertCall.cpp b/flang/lib/Lower/ConvertCall.cpp
index de17170614ad5..bcf68c367b598 100644
--- a/flang/lib/Lower/ConvertCall.cpp
+++ b/flang/lib/Lower/ConvertCall.cpp
@@ -931,9 +931,8 @@ static hlfir::EntityWithAttributes genStmtFunctionRef(
assert(arg && "alternate return in statement function");
assert(bind && "optional argument in statement function");
const auto *expr = bind->UnwrapExpr();
- // TODO: assumed type in statement function, that surprisingly seems
- // allowed, probably because nobody thought of restricting this usage.
- // gfortran/ifort compiles this.
+ // Assumed-type entities cannot be statement function dummy arguments
+ // (F2023 15.6.4); semantics rejects them in HandleStmtFunction.
assert(expr && "assumed type used as statement function argument");
// As per Fortran 2018 C1580, statement function arguments can only be
// scalars.
diff --git a/flang/lib/Semantics/check-declarations.cpp b/flang/lib/Semantics/check-declarations.cpp
index 9e783915039ba..0807ac5f56aa6 100644
--- a/flang/lib/Semantics/check-declarations.cpp
+++ b/flang/lib/Semantics/check-declarations.cpp
@@ -1701,6 +1701,28 @@ void CheckHelper::CheckSubprogram(
*host);
}
}
+ // F2023 15.6.4: the length of a CHARACTER statement function result or
+ // dummy argument shall be a constant specification expression.
+ auto checkCharLength{[&](const Symbol &entity, const char *what) {
+ if (const DeclTypeSpec * type{entity.GetType()};
+ type && type->category() == DeclTypeSpec::Character) {
+ const ParamValue &length{type->characterTypeSpec().length()};
+ if (length.isExplicit() && length.GetExplicit() &&
+ !evaluate::IsConstantExpr(*length.GetExplicit())) {
+ Warn(common::LanguageFeature::StatementFunctionExtensions,
+ entity.name(),
+ "The length of %s '%s' should be a constant expression"_port_en_US,
+ what, entity.name());
+ }
+ }
+ }};
+ checkCharLength(details.result(), "CHARACTER statement function result");
+ for (const Symbol *dummy : details.dummyArgs()) {
+ if (dummy) {
+ checkCharLength(
+ *dummy, "CHARACTER statement function dummy argument");
+ }
+ }
if (GetProgramUnitOrBlockConstructContaining(symbol).kind() ==
Scope::Kind::BlockConstruct) { // C1107
messages_.Say(symbol.name(),
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index 3d06f7d1fa495..b58801b222072 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -5267,7 +5267,13 @@ bool SubprogramVisitor::HandleStmtFunction(const parser::StmtFunctionStmt &x) {
ObjectEntityDetails dummyDetails{true};
if (auto *dummySymbol{FindInScope(currScope().parent(), dummyName)}) {
if (auto *d{dummySymbol->GetType()}) {
- dummyDetails.set_type(*d);
+ if (d->IsAssumedType()) {
+ Say(dummyName.source,
+ "Statement function dummy argument '%s' cannot have assumed type"_err_en_US,
+ dummyName.source);
+ } else {
+ dummyDetails.set_type(*d);
+ }
}
}
Symbol &dummy{MakeSymbol(dummyName, std::move(dummyDetails))};
diff --git a/flang/test/Semantics/stmt-func05.f90 b/flang/test/Semantics/stmt-func05.f90
new file mode 100644
index 0000000000000..b2dd9dab7d349
--- /dev/null
+++ b/flang/test/Semantics/stmt-func05.f90
@@ -0,0 +1,56 @@
+! RUN: %python %S/test_errors.py %s %flang_fc1 -pedantic
+! A statement function dummy argument takes its type from the entity of the
+! same name in the enclosing scope, which cannot be assumed-type.
+subroutine s1(a)
+ type(*) :: a
+ integer :: func
+ !ERROR: Statement function dummy argument 'a' cannot have assumed type
+ func(a) = 1
+end subroutine
+
+! F2023 15.6.4
+subroutine s2(a, n)
+ integer :: a
+ integer :: n
+ character(len=n) :: func
+ !PORTABILITY: The length of CHARACTER statement function result 'func' should be a constant expression [-Wstatement-function-extensions]
+ func(a) = "hello"
+end subroutine
+
+subroutine s3(a)
+ integer :: a
+ integer :: c
+ real :: func
+ func(a) = 1
+ c = func(a)
+end subroutine
+
+subroutine s4(a)
+ integer :: a
+ character(len=5) :: func
+ func(a) = "hello"
+end subroutine
+
+subroutine s5(x)
+ character(len=10) :: x
+ character(len=10) :: func
+ func(x) = x
+end subroutine
+
+subroutine s6(x, n)
+ integer :: n
+ character(len=n) :: x
+ integer :: func
+ !PORTABILITY: The length of CHARACTER statement function dummy argument 'x' should be a constant expression [-Wstatement-function-extensions]
+ func(x) = 1
+end subroutine
+
+subroutine s7(a)
+ type(*) :: a
+ integer :: c
+ integer :: func
+ !ERROR: Statement function dummy argument 'a' cannot have assumed type
+ func(a) = 1
+ !ERROR: Assumed-type 'a' may be associated only with an assumed-type dummy argument 'a='
+ c = func(a)
+end subroutine
>From 89f39991caca4868f78585ecdeba44c0cdbd1488 Mon Sep 17 00:00:00 2001
From: shrikuma <Shrisha.Kumar at amd.com>
Date: Wed, 14 Oct 2026 14:18:28 +0530
Subject: [PATCH 2/2] [flang] Reuse DynamicType::IsNonConstantLengthCharacter
---
flang/lib/Semantics/check-declarations.cpp | 19 +++++++------------
1 file changed, 7 insertions(+), 12 deletions(-)
diff --git a/flang/lib/Semantics/check-declarations.cpp b/flang/lib/Semantics/check-declarations.cpp
index 0807ac5f56aa6..209956d538377 100644
--- a/flang/lib/Semantics/check-declarations.cpp
+++ b/flang/lib/Semantics/check-declarations.cpp
@@ -1704,23 +1704,18 @@ void CheckHelper::CheckSubprogram(
// F2023 15.6.4: the length of a CHARACTER statement function result or
// dummy argument shall be a constant specification expression.
auto checkCharLength{[&](const Symbol &entity, const char *what) {
- if (const DeclTypeSpec * type{entity.GetType()};
- type && type->category() == DeclTypeSpec::Character) {
- const ParamValue &length{type->characterTypeSpec().length()};
- if (length.isExplicit() && length.GetExplicit() &&
- !evaluate::IsConstantExpr(*length.GetExplicit())) {
- Warn(common::LanguageFeature::StatementFunctionExtensions,
- entity.name(),
- "The length of %s '%s' should be a constant expression"_port_en_US,
- what, entity.name());
- }
+ if (auto type{evaluate::DynamicType::From(entity)};
+ type && type->IsNonConstantLengthCharacter()) {
+ Warn(common::LanguageFeature::StatementFunctionExtensions,
+ entity.name(),
+ "The length of %s '%s' should be a constant expression"_port_en_US,
+ what, entity.name());
}
}};
checkCharLength(details.result(), "CHARACTER statement function result");
for (const Symbol *dummy : details.dummyArgs()) {
if (dummy) {
- checkCharLength(
- *dummy, "CHARACTER statement function dummy argument");
+ checkCharLength(*dummy, "CHARACTER statement function dummy argument");
}
}
if (GetProgramUnitOrBlockConstructContaining(symbol).kind() ==
More information about the flang-commits
mailing list