[flang-commits] [flang] 1fddb91 - [Flang][Semantics] Diagnose missing MODULE prefix in submodule procedures (#197173)

via flang-commits flang-commits at lists.llvm.org
Tue Sep 8 21:55:03 PDT 2026


Author: ShashwathiNavada
Date: 2026-09-09T10:24:58+05:30
New Revision: 1fddb91bf4ad2c3012c107f0cf792e2b2a5a9b67

URL: https://github.com/llvm/llvm-project/commit/1fddb91bf4ad2c3012c107f0cf792e2b2a5a9b67
DIFF: https://github.com/llvm/llvm-project/commit/1fddb91bf4ad2c3012c107f0cf792e2b2a5a9b67.diff

LOG: [Flang][Semantics] Diagnose missing MODULE prefix in submodule procedures (#197173)

Add a portability warning when a submodule procedure is missing the
MODULE prefix required by a MODULE PROCEDURE interface in its parent
module.

Added: 
    flang/test/Semantics/modfile86.f90
    flang/test/Semantics/modfile87.f90
    flang/test/Semantics/resolve132.f90

Modified: 
    flang/lib/Semantics/resolve-names.cpp

Removed: 
    


################################################################################
diff  --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index fccaa87e0175f..af91064aa340d 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -5983,6 +5983,27 @@ const Symbol *SubprogramVisitor::CheckExtantProc(
 Symbol *SubprogramVisitor::PushSubprogramScope(const parser::Name &name,
     Symbol::Flag subpFlag, const parser::LanguageBindingSpec *bindingSpec,
     bool hasModulePrefix) {
+  if (!inInterfaceBlock() && currScope().IsSubmodule() && !hasModulePrefix) {
+    const Scope &parent{currScope().parent()};
+    if (parent.IsModule() || parent.IsSubmodule()) {
+      if (const Symbol *host{parent.FindSymbol(name.source)}) {
+        const Symbol &hostUlt{host->GetUltimate()};
+        const auto *hostSubp{hostUlt.detailsIf<SubprogramDetails>()};
+        if (IsSeparateModuleProcedureInterface(&hostUlt)) {
+          // Use the low-level Warn() call to avoid module-file suppression
+          // based on scope ancestry; InModuleFile() provides the appropriate
+          // check here.
+          context().messages().Warn(/*isInModuleFile=*/InModuleFile(),
+              context().languageFeatures(), common::UsageWarning::Portability,
+              name.source,
+              "Subprogram '%s' in this submodule is missing the MODULE prefix "
+              "to implement the module procedure interface from its parent; "
+              "did you mean 'MODULE %s'?"_port_en_US,
+              name.source, hostSubp->isFunction() ? "FUNCTION" : "SUBROUTINE");
+        }
+      }
+    }
+  }
   Symbol *symbol{GetSpecificFromGeneric(name)};
   const DeclTypeSpec *previousImplicitType{nullptr};
   SourceName previousName;

diff  --git a/flang/test/Semantics/modfile86.f90 b/flang/test/Semantics/modfile86.f90
new file mode 100644
index 0000000000000..5ab719d95b91e
--- /dev/null
+++ b/flang/test/Semantics/modfile86.f90
@@ -0,0 +1,36 @@
+! RUN: split-file %s %t
+! RUN: %flang_fc1 -fsyntax-only -J%t %t/a.f90
+! RUN: %flang_fc1 -fsyntax-only -J%t %t/b.f90
+! RUN: %flang_fc1 -fsyntax-only -pedantic -J%t %t/c.f90 2>&1 | FileCheck --allow-empty %s
+
+! Compiling a submodule of a submodule ("b") must not
+! resurface "b"'s own missing-MODULE-prefix portability warning when "b" is
+! re-read from its .smod file as a dependency of "c".
+
+!--- a.f90
+module modfile86a
+  interface
+    module subroutine inside_one()
+    end subroutine
+  end interface
+end module
+
+!--- b.f90
+submodule (modfile86a) modfile86b
+  interface
+    module subroutine inside_two()
+    end subroutine
+  end interface
+contains
+  subroutine inside_one()
+  end subroutine
+end submodule
+
+!--- c.f90
+submodule (modfile86a:modfile86b) modfile86c
+contains
+  module subroutine inside_two()
+  end subroutine
+end submodule
+
+!CHECK-NOT: portability

diff  --git a/flang/test/Semantics/modfile87.f90 b/flang/test/Semantics/modfile87.f90
new file mode 100644
index 0000000000000..a915b8310df3e
--- /dev/null
+++ b/flang/test/Semantics/modfile87.f90
@@ -0,0 +1,25 @@
+! RUN: split-file %s %t
+! RUN: %flang_fc1 -fsyntax-only -J%t %t/m.f90
+! RUN: %flang_fc1 -fsyntax-only -pedantic -J%t %t/s.f90 2>&1 | FileCheck %s
+
+! When a module and its submodule are compiled in separate
+! invocations (so that the submodule's parent module scope is read back from
+! the .mod file), the "missing MODULE prefix" portability warning for the
+! submodule's subprogram must still be emitted.
+
+!--- m.f90
+module modfile87m
+  interface
+    module subroutine inside_one()
+    end subroutine
+  end interface
+end module
+
+!--- s.f90
+submodule (modfile87m) modfile87s
+contains
+  subroutine inside_one()
+  end subroutine
+end submodule
+
+!CHECK: portability: Subprogram 'inside_one' in this submodule is missing the MODULE prefix

diff  --git a/flang/test/Semantics/resolve132.f90 b/flang/test/Semantics/resolve132.f90
new file mode 100644
index 0000000000000..2c1575af7c370
--- /dev/null
+++ b/flang/test/Semantics/resolve132.f90
@@ -0,0 +1,48 @@
+! RUN: %python %S/test_errors.py %s %flang_fc1 -pedantic -Werror
+
+module parent_mod_9
+   interface
+      module subroutine inside_one()
+      end subroutine
+   end interface
+ end module
+
+ submodule (parent_mod_9) sub_9
+ contains
+   !PORTABILITY: Subprogram 'inside_one' in this submodule is missing the MODULE prefix to implement the module procedure interface from its parent; did you mean 'MODULE SUBROUTINE'? [-Wportability]
+   subroutine inside_one()
+   end subroutine
+ end submodule
+
+! Same check for a function.
+module parent_mod_9f
+   interface
+      module integer function inside_func()
+      end function
+   end interface
+ end module
+
+ submodule (parent_mod_9f) sub_9f
+ contains
+   !PORTABILITY: Subprogram 'inside_func' in this submodule is missing the MODULE prefix to implement the module procedure interface from its parent; did you mean 'MODULE FUNCTION'? [-Wportability]
+   integer function inside_func()
+     inside_func = 0
+   end function
+ end submodule
+
+module m2
+  interface
+    module subroutine sub()
+    end subroutine
+  end interface
+end module
+
+submodule (m2) s2
+contains
+   !PORTABILITY: Subprogram 'sub' in this submodule is missing the MODULE prefix to implement the module procedure interface from its parent; did you mean 'MODULE SUBROUTINE'? [-Wportability]
+  integer function sub()
+    sub = 2
+  end function
+end submodule
+Program abc
+end


        


More information about the flang-commits mailing list