[flang-commits] [flang] [flang] Reject interface name declared by a later PROCEDURE statement (PR #232928)
via flang-commits
flang-commits at lists.llvm.org
Fri Oct 16 23:12:04 PDT 2026
https://github.com/Glitch-On updated https://github.com/llvm/llvm-project/pull/232928
>From 9150bb3a436bd72f6a0f4c304963ea9a58aed6fb Mon Sep 17 00:00:00 2001
From: Vansh <gaurvansh133 at gmail.com>
Date: Sat, 17 Oct 2026 01:22:48 +0530
Subject: [PATCH 1/2] [flang] Reject interface name declared by a later
PROCEDURE statement
C1515 requires that a name used as a procedure interface, when it is
itself declared by a procedure declaration statement, be declared before
that use. Name resolution creates a placeholder symbol for a forward
reference and only checks it after the whole specification part, by which
point the later PROCEDURE statement has given it an explicit interface, so
the program was accepted.
In the deferred check, report an error when the interface name resolves to
a procedure entity whose declaration comes after the use. Forward
references to interface bodies and module procedures are still accepted.
Fixes #229229
---
flang/lib/Semantics/resolve-names.cpp | 19 +++++++++++++
flang/test/Semantics/procinterface06.f90 | 36 ++++++++++++++++++++++++
2 files changed, 55 insertions(+)
create mode 100644 flang/test/Semantics/procinterface06.f90
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index d0964294d10c03..cf315147bdf029 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -1187,6 +1187,7 @@ class DeclarationVisitor : public ArraySpecVisitor,
void LegacyDataInitialization(const parser::Name &,
const std::list<common::Indirection<parser::DataStmtValue>> &values);
void CheckExplicitInterface(const parser::Name &);
+ void CheckInterfaceNameDeclaredBeforeUse(const parser::Name &);
void CheckBindings(const parser::TypeBoundProcedureStmt::WithoutInterface &);
const parser::Name *ResolveDesignator(const parser::Designator &);
@@ -8816,6 +8817,23 @@ void DeclarationVisitor::CheckExplicitInterface(const parser::Name &name) {
}
}
+// C1515: a name that is declared by a procedure-declaration-stmt may be
+// used as an interface name only after that declaration.
+void DeclarationVisitor::CheckInterfaceNameDeclaredBeforeUse(
+ const parser::Name &name) {
+ if (const Symbol * symbol{name.symbol}) {
+ if (!context().HasError(*symbol) && symbol->has<ProcEntityDetails>() &&
+ symbol->HasExplicitInterface() &&
+ context().allCookedSources().Precedes(name.source, symbol->name())) {
+ Say(name,
+ "'%s' must be declared before it is used as a procedure interface"_err_en_US,
+ symbol->name())
+ .Attach(symbol->name(), "Later declaration of '%s'"_en_US,
+ symbol->name());
+ }
+ }
+}
+
// Create a symbol for a type parameter, component, or procedure binding in
// the current derived type scope. Return false on error.
Symbol *DeclarationVisitor::MakeTypeSymbol(
@@ -11977,6 +11995,7 @@ class DeferredCheckVisitor {
void Post(const parser::ProcInterface &pi) {
if (const auto *name{std::get_if<parser::Name>(&pi.u)}) {
resolver_.CheckExplicitInterface(*name);
+ resolver_.CheckInterfaceNameDeclaredBeforeUse(*name);
}
}
bool Pre(const parser::EntityDecl &decl) {
diff --git a/flang/test/Semantics/procinterface06.f90 b/flang/test/Semantics/procinterface06.f90
new file mode 100644
index 00000000000000..ed2570cdaa0a18
--- /dev/null
+++ b/flang/test/Semantics/procinterface06.f90
@@ -0,0 +1,36 @@
+! RUN: %python %S/test_errors.py %s %flang_fc1
+! C1515: a name declared by a PROCEDURE statement may be used as an
+! interface name only after that declaration.
+module m
+ implicit none
+ abstract interface
+ subroutine s_iface()
+ end subroutine
+ end interface
+ !ERROR: 'q' must be declared before it is used as a procedure interface
+ procedure(q), pointer :: r
+ !ERROR: 'q' must be declared before it is used as a procedure interface
+ procedure(q) :: r2
+ procedure(s_iface), pointer :: q
+ procedure(q), pointer :: t ! ok, q is declared above
+ procedure(later), pointer :: u ! ok, later is declared by an interface body
+ interface
+ subroutine later()
+ end subroutine
+ end interface
+ type dt
+ !ERROR: 'q2' must be declared before it is used as a procedure interface
+ procedure(q2), pointer, nopass :: comp
+ end type
+ procedure(s_iface), pointer :: q2
+end module
+
+subroutine sub(a, b)
+ abstract interface
+ subroutine s_iface()
+ end subroutine
+ end interface
+ !ERROR: 'b' must be declared before it is used as a procedure interface
+ procedure(b), pointer :: a
+ procedure(s_iface) :: b
+end subroutine
>From 9101b514525a96afb704d7ec7a98437a07e41f56 Mon Sep 17 00:00:00 2001
From: Vansh <gaurvansh133 at gmail.com>
Date: Sat, 17 Oct 2026 11:41:53 +0530
Subject: [PATCH 2/2] Fix clang-format issue
---
flang/lib/Semantics/resolve-names.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index cf315147bdf029..400ccc020df9d1 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -8821,7 +8821,7 @@ void DeclarationVisitor::CheckExplicitInterface(const parser::Name &name) {
// used as an interface name only after that declaration.
void DeclarationVisitor::CheckInterfaceNameDeclaredBeforeUse(
const parser::Name &name) {
- if (const Symbol * symbol{name.symbol}) {
+ if (const Symbol *symbol{name.symbol}) {
if (!context().HasError(*symbol) && symbol->has<ProcEntityDetails>() &&
symbol->HasExplicitInterface() &&
context().allCookedSources().Precedes(name.source, symbol->name())) {
More information about the flang-commits
mailing list