[flang-commits] [flang] 4148d0b - [flang] Reject type bound procedure overrides with mismatched passed-object dummy names (#210876)
via flang-commits
flang-commits at lists.llvm.org
Sun Aug 2 21:37:30 PDT 2026
Author: ejose02
Date: 2026-08-03T10:07:25+05:30
New Revision: 4148d0b61dfe9f5fa1fd5c7cde9c34d4ea92cb8b
URL: https://github.com/llvm/llvm-project/commit/4148d0b61dfe9f5fa1fd5c7cde9c34d4ea92cb8b
DIFF: https://github.com/llvm/llvm-project/commit/4148d0b61dfe9f5fa1fd5c7cde9c34d4ea92cb8b.diff
LOG: [flang] Reject type bound procedure overrides with mismatched passed-object dummy names (#210876)
Fixes #206913
Issue:
Flang wrongly accepts a type-bound procedure override when the
implementing procedure uses a different dummy name than the parent
deferred interface.
Root cause:
The PASS override check uses CanOverride, which compares dummy types but
not dummy names for the passed-object argument.
Fix:
Check that dummy names match before CanOverride and report a clear error
Added:
flang/test/Semantics/bindings08.f90
Modified:
flang/lib/Semantics/check-declarations.cpp
Removed:
################################################################################
diff --git a/flang/lib/Semantics/check-declarations.cpp b/flang/lib/Semantics/check-declarations.cpp
index 0a62e199d9779..41ddb61c4340d 100644
--- a/flang/lib/Semantics/check-declarations.cpp
+++ b/flang/lib/Semantics/check-declarations.cpp
@@ -2700,6 +2700,19 @@ void CheckHelper::CheckPassArg(
}
}
+static std::optional<std::size_t> FindOverrideDummyNameMismatch(
+ const Procedure &binding, const Procedure &overridden) {
+ if (binding.dummyArguments.size() != overridden.dummyArguments.size()) {
+ return std::nullopt;
+ }
+ for (std::size_t j{0}; j < binding.dummyArguments.size(); ++j) {
+ if (binding.dummyArguments[j].name != overridden.dummyArguments[j].name) {
+ return j;
+ }
+ }
+ return std::nullopt;
+}
+
void CheckHelper::CheckProcBinding(
const Symbol &symbol, const ProcBindingDetails &binding) {
const Scope &dtScope{symbol.owner()};
@@ -2770,7 +2783,14 @@ void CheckHelper::CheckProcBinding(
const auto *bindingChars{Characterize(symbol)};
const auto *overriddenChars{Characterize(*overridden)};
if (bindingChars && overriddenChars) {
- if (isNopass) {
+ if (auto mismatch{FindOverrideDummyNameMismatch(
+ *bindingChars, *overriddenChars)}) {
+ SayWithDeclaration(*overridden,
+ "Dummy argument '%s' of type-bound procedure '%s' must "
+ "correspond by name to '%s' in the overridden procedure"_err_en_US,
+ bindingChars->dummyArguments[*mismatch].name, symbol.name(),
+ overriddenChars->dummyArguments[*mismatch].name);
+ } else if (isNopass) {
if (!bindingChars->CanOverride(*overriddenChars, std::nullopt)) {
SayWithDeclaration(*overridden,
"A NOPASS type-bound procedure and its override must have identical interfaces"_err_en_US);
diff --git a/flang/test/Semantics/bindings08.f90 b/flang/test/Semantics/bindings08.f90
new file mode 100644
index 0000000000000..bfc118cd74308
--- /dev/null
+++ b/flang/test/Semantics/bindings08.f90
@@ -0,0 +1,118 @@
+! RUN: %python %S/test_errors.py %s %flang_fc1
+
+module m
+ type, abstract :: parent
+ contains
+ procedure(ip), deferred :: set
+ end type
+ abstract interface
+ subroutine ip(x)
+ import parent
+ class(parent) :: x
+ end subroutine
+ end interface
+ type, public, extends(parent), abstract :: child
+ end type
+ type, extends(child) :: grandchild
+ contains
+ !ERROR: Dummy argument 'y' of type-bound procedure 'set' must correspond by name to 'x' in the overridden procedure
+ procedure :: set
+ end type
+ contains
+ subroutine set(y)
+ class(grandchild) :: y
+ end subroutine
+end module
+
+! Valid override with matching dummy names
+module m_ok
+ type, abstract :: t
+ contains
+ procedure(ip), deferred :: set
+ end type
+ abstract interface
+ subroutine ip(x)
+ import t
+ class(t) :: x
+ end subroutine
+ end interface
+ type, extends(t) :: e
+ contains
+ procedure :: set
+ end type
+ contains
+ subroutine set(x)
+ class(e) :: x
+ end subroutine
+end module
+
+! Extra dummy argument: interface mismatch, not a name error
+module m_extra
+ type, abstract :: t
+ contains
+ procedure(ip), deferred :: set
+ end type
+ abstract interface
+ subroutine ip(x)
+ import t
+ class(t) :: x
+ end subroutine
+ end interface
+ type, extends(t) :: e
+ contains
+ !ERROR: A type-bound procedure and its override must have compatible interfaces
+ procedure :: set
+ end type
+ contains
+ subroutine set(x, n)
+ class(e) :: x
+ integer :: n
+ end subroutine
+end module
+
+! Non-pass dummy renamed
+module m_rename
+ type, abstract :: t
+ contains
+ procedure(ip), deferred :: set
+ end type
+ abstract interface
+ subroutine ip(x, n)
+ import t
+ class(t) :: x
+ integer :: n
+ end subroutine
+ end interface
+ type, extends(t) :: e
+ contains
+ !ERROR: Dummy argument 'm2' of type-bound procedure 'set' must correspond by name to 'n' in the overridden procedure
+ procedure :: set
+ end type
+ contains
+ subroutine set(x, m2)
+ class(e) :: x
+ integer :: m2
+ end subroutine
+end module
+
+! NOPASS deferred override with mismatched dummy name
+module m_nopass
+ type, abstract :: t
+ contains
+ procedure(ip), deferred, nopass :: act
+ end type
+ abstract interface
+ subroutine ip(a)
+ integer :: a
+ end subroutine
+ end interface
+ type, extends(t) :: e
+ contains
+ !ERROR: Dummy argument 'b' of type-bound procedure 'act' must correspond by name to 'a' in the overridden procedure
+ procedure, nopass :: act => impl
+ end type
+ contains
+ subroutine impl(b)
+ integer :: b
+ end subroutine
+end module
More information about the flang-commits
mailing list