[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