[flang-commits] [flang] b01d034 - [Flang] Reject keyword arguments in statement function calls (#198610)
via flang-commits
flang-commits at lists.llvm.org
Thu Jun 11 03:16:23 PDT 2026
Author: jay0x
Date: 2026-06-11T15:46:18+05:30
New Revision: b01d0342c129405c30947f459cf055bbe8846974
URL: https://github.com/llvm/llvm-project/commit/b01d0342c129405c30947f459cf055bbe8846974
DIFF: https://github.com/llvm/llvm-project/commit/b01d0342c129405c30947f459cf055bbe8846974.diff
LOG: [Flang] Reject keyword arguments in statement function calls (#198610)
**Problem**
Flang silently accepted keyword arguments in calls to statement
functions, violating F2018 C1535.
**Standard: F2018 ยง15.5.1 C1535**: In a reference to a procedure whose
interface is implicit at the point of the reference, the actual argument
shall not be a keyword argument.
Flang silently compiles the following code without giving error` Keyword
argument 'x' at (1) is invalid in a statement function
`
```
program test
integer :: f1, x, c
f1(x) = x / 2
c = f1(x=10) ! Should be an error
end program
```
**Summary**
Fixed an issue where statement functions were incorrectly treated as
having an explicit interface, causing argument checks to be skipped.
Now, statement functions are marked correctly so existing checks run and
proper errors are shown
**Fixes** : [198523](https://github.com/llvm/llvm-project/issues/198523)
---------
Co-authored-by: Jay Satish Kumar Patel <kumarpat at pe31.hpc.amslabs.hpecorp.net>
Added:
flang/test/Semantics/call47.f90
Modified:
flang/lib/Semantics/check-call.cpp
flang/lib/Semantics/check-call.h
flang/lib/Semantics/expression.cpp
Removed:
################################################################################
diff --git a/flang/lib/Semantics/check-call.cpp b/flang/lib/Semantics/check-call.cpp
index da8880482d4dc..dcd7dc4288f6f 100644
--- a/flang/lib/Semantics/check-call.cpp
+++ b/flang/lib/Semantics/check-call.cpp
@@ -27,7 +27,7 @@ namespace characteristics = Fortran::evaluate::characteristics;
namespace Fortran::semantics {
-static void CheckImplicitInterfaceArg(evaluate::ActualArgument &arg,
+void CheckImplicitInterfaceArg(evaluate::ActualArgument &arg,
parser::ContextualMessages &messages, SemanticsContext &context) {
auto restorer{
messages.SetLocation(arg.sourceLocation().value_or(messages.at()))};
diff --git a/flang/lib/Semantics/check-call.h b/flang/lib/Semantics/check-call.h
index a69b792b646e6..fb021d23dabc8 100644
--- a/flang/lib/Semantics/check-call.h
+++ b/flang/lib/Semantics/check-call.h
@@ -25,6 +25,11 @@ namespace Fortran::semantics {
class Scope;
class SemanticsContext;
+// Check constraints on actual arguments for procedures with implicit
+// interfaces. Used for statement function calls and external procedures.
+void CheckImplicitInterfaceArg(evaluate::ActualArgument &,
+ parser::ContextualMessages &, SemanticsContext &);
+
// Argument treatingExternalAsImplicit should be true when the called procedure
// does not actually have an explicit interface at the call site, but
// its characteristics are known because it is a subroutine or function
diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp
index 50869a3c870ef..66eeaae2c9ff1 100644
--- a/flang/lib/Semantics/expression.cpp
+++ b/flang/lib/Semantics/expression.cpp
@@ -3778,6 +3778,9 @@ std::optional<characteristics::Procedure> ExpressionAnalyzer::CheckCall(
bool treatExternalAsImplicit{
IsExternalCalledImplicitly(callSite, proc.GetSymbol())};
const Symbol *procSymbol{proc.GetSymbol()};
+ // Statement functions have implicit interfaces and require the same checks
+ bool isStatementFunction{
+ procSymbol && procSymbol->flags().test(Symbol::Flag::StmtFunction)};
std::optional<characteristics::Procedure> chars;
if (procSymbol && procSymbol->has<semantics::ProcEntityDetails>() &&
procSymbol->owner().IsGlobal()) {
@@ -3847,6 +3850,17 @@ std::optional<characteristics::Procedure> ExpressionAnalyzer::CheckCall(
name, DEREF(pure->symbol()).name());
}
}
+ if (isStatementFunction) {
+ // Statement functions have implicit interfaces; check for
+ // keyword arguments and other implicit interface constraints
+ parser::ContextualMessages &messages{
+ context_.foldingContext().messages()};
+ for (auto &arg : arguments) {
+ if (arg) {
+ semantics::CheckImplicitInterfaceArg(*arg, messages, context_);
+ }
+ }
+ }
ok &= semantics::CheckArguments(*chars, arguments, context_,
context_.FindScope(callSite), treatExternalAsImplicit,
/*ignoreImplicitVsExplicit=*/false, specificIntrinsic);
diff --git a/flang/test/Semantics/call47.f90 b/flang/test/Semantics/call47.f90
new file mode 100644
index 0000000000000..0c6e9071f33f0
--- /dev/null
+++ b/flang/test/Semantics/call47.f90
@@ -0,0 +1,26 @@
+! RUN: %python %S/test_errors.py %s %flang_fc1
+! Test F2018 15.5.1 C1535 - keyword arguments are not allowed when the
+! interface is implicit. Statement functions have implicit interfaces.
+
+program test_stmt_func_keyword
+ integer :: f1, f2, x, y, c
+
+ ! Statement function definitions
+ f1(x) = x / 2
+ f2(x, y) = x + y
+
+ ! Calling a statement function with a keyword argument is not allowed
+ ! because statement functions have implicit interfaces.
+ !ERROR: Keyword 'x=' may not appear in a reference to a procedure with an implicit interface
+ c = f1(x=10)
+
+ ! Wrong keyword name - gets both implicit interface error and unrecognized keyword error
+ !ERROR: Keyword 'y=' may not appear in a reference to a procedure with an implicit interface
+ !ERROR: Argument keyword 'y=' is not recognized for this procedure reference
+ c = f1(y=10)
+
+ ! Two keyword arguments - each gets its own diagnostic
+ !ERROR: Keyword 'x=' may not appear in a reference to a procedure with an implicit interface
+ !ERROR: Keyword 'y=' may not appear in a reference to a procedure with an implicit interface
+ c = f2(x=10, y=20)
+end program
More information about the flang-commits
mailing list