[flang-commits] [flang] [Flang] External subprograms should be allowed as proc_target in procedure pointers. (PR #183268)

via flang-commits flang-commits at lists.llvm.org
Thu Mar 12 08:22:29 PDT 2026


https://github.com/ShashwathiNavada updated https://github.com/llvm/llvm-project/pull/183268

>From dc876977bdf7e5c7ed8639047829a8dc1e93c7e5 Mon Sep 17 00:00:00 2001
From: ShashwathiNavada <shashwathinavada at gmail.com>
Date: Wed, 25 Feb 2026 04:00:02 -0600
Subject: [PATCH 1/3] External subprograms should be allowed as proc_target in
 procedure pointers

---
 flang/lib/Lower/CallInterface.cpp   | 15 +++++++++++++++
 flang/test/Semantics/extrn_subp.f90 | 20 ++++++++++++++++++++
 2 files changed, 35 insertions(+)
 create mode 100644 flang/test/Semantics/extrn_subp.f90

diff --git a/flang/lib/Lower/CallInterface.cpp b/flang/lib/Lower/CallInterface.cpp
index f5ae2de5cad8b..65cac0466d5ea 100644
--- a/flang/lib/Lower/CallInterface.cpp
+++ b/flang/lib/Lower/CallInterface.cpp
@@ -695,6 +695,21 @@ void Fortran::lower::CallInterface<T>::declare() {
     mlir::ModuleOp module = converter.getModuleOp();
     mlir::SymbolTable *symbolTable = converter.getMLIRSymbolTable();
     func = fir::FirOpBuilder::getNamedFunction(module, symbolTable, name);
+    if (func) {
+      if constexpr (std::is_same_v<T, Fortran::lower::CalleeInterface>) {
+        mlir::FunctionType ty = genFunctionType();
+        if (!func.getBlocks().empty())
+          fir::emitFatalError(
+              func.getLoc(),
+              "conflicting procedure definition with mismatched signature");
+        if (func.getFunctionType() != ty) {
+          func.setType(ty);
+          for (const auto &placeHolder : llvm::enumerate(inputs))
+            func.setArgAttrs(placeHolder.index(),
+                             placeHolder.value().attributes);
+        }
+      }
+    }
     if (!func) {
       mlir::Location loc = side().getCalleeLocation();
       mlir::MLIRContext &mlirContext = converter.getMLIRContext();
diff --git a/flang/test/Semantics/extrn_subp.f90 b/flang/test/Semantics/extrn_subp.f90
new file mode 100644
index 0000000000000..67b3b02a85363
--- /dev/null
+++ b/flang/test/Semantics/extrn_subp.f90
@@ -0,0 +1,20 @@
+! RUN: flang %s
+
+Module m1
+  external::sub
+  type ty
+    procedure(),pointer,nopass :: ptr5=>sub
+  end type
+  procedure(),pointer:: ptr6=>sub
+end module
+ 
+use m1
+  integer::jj =4
+  call ptr6(10)
+  print*,"Pass"
+end
+ 
+subroutine sub(a)
+  integer::a
+  print*,"sub"
+end subroutine
\ No newline at end of file

>From 2fe4d47094b0e5bc9cbc9271f95f2833a3966774 Mon Sep 17 00:00:00 2001
From: ShashwathiNavada <shashwathinavada at gmail.com>
Date: Wed, 25 Feb 2026 06:31:09 -0600
Subject: [PATCH 2/3] Simple changes

---
 flang/test/Semantics/extrn_subp.f90 | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/flang/test/Semantics/extrn_subp.f90 b/flang/test/Semantics/extrn_subp.f90
index 67b3b02a85363..5336daf22d248 100644
--- a/flang/test/Semantics/extrn_subp.f90
+++ b/flang/test/Semantics/extrn_subp.f90
@@ -1,4 +1,4 @@
-! RUN: flang %s
+! RUN: %python %S/test_errors.py %s %flang_fc1
 
 Module m1
   external::sub

>From 2bf192fff0669703fb080bbf1f032a199eb3be63 Mon Sep 17 00:00:00 2001
From: ShashwathiNavada <shashwathinavada at gmail.com>
Date: Thu, 12 Mar 2026 10:21:33 -0500
Subject: [PATCH 3/3] Suggested change

---
 flang/lib/Lower/Bridge.cpp          | 19 +++++++++++++++++-
 flang/lib/Lower/CallInterface.cpp   | 15 ---------------
 flang/test/Lower/extrn_subp.f90     | 30 +++++++++++++++++++++++++++++
 flang/test/Semantics/extrn_subp.f90 |  2 +-
 4 files changed, 49 insertions(+), 17 deletions(-)
 create mode 100644 flang/test/Lower/extrn_subp.f90

diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index 687c2f0f4a42a..10999e38883ba 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -507,7 +507,6 @@ class FirConverter : public Fortran::lower::AbstractConverter {
                     globalOmpRequiresSymbol = f.getScope().symbol();
                 },
                 [&](Fortran::lower::pft::ModuleLikeUnit &m) {
-                  lowerModuleDeclScope(m);
                   for (Fortran::lower::pft::ContainedUnit &unit :
                        m.containedUnitList)
                     if (auto *f =
@@ -526,6 +525,24 @@ class FirConverter : public Fortran::lower::AbstractConverter {
       }
     });
 
+    // Lower module declaration scopes now that all function
+    // declarations are available with their final signatures.
+    createBuilderOutsideOfFuncOpAndDo([&]() {
+      for (Fortran::lower::pft::Program::Units &u : pft.getUnits()) {
+        Fortran::common::visit(
+            Fortran::common::visitors{
+                [&](Fortran::lower::pft::FunctionLikeUnit &f) {},
+                [&](Fortran::lower::pft::ModuleLikeUnit &m) {
+                  lowerModuleDeclScope(m);
+                },
+                [&](Fortran::lower::pft::BlockDataUnit &b) {},
+                [&](Fortran::lower::pft::CompilerDirectiveUnit &d) {},
+                [&](Fortran::lower::pft::OpenACCDirectiveUnit &d) {},
+            },
+            u);
+      }
+    });
+
     // Ensure imported OpenMP declare mappers are materialized at module
     // scope before lowering any constructs that may reference them.
     createBuilderOutsideOfFuncOpAndDo([&]() {
diff --git a/flang/lib/Lower/CallInterface.cpp b/flang/lib/Lower/CallInterface.cpp
index 65cac0466d5ea..f5ae2de5cad8b 100644
--- a/flang/lib/Lower/CallInterface.cpp
+++ b/flang/lib/Lower/CallInterface.cpp
@@ -695,21 +695,6 @@ void Fortran::lower::CallInterface<T>::declare() {
     mlir::ModuleOp module = converter.getModuleOp();
     mlir::SymbolTable *symbolTable = converter.getMLIRSymbolTable();
     func = fir::FirOpBuilder::getNamedFunction(module, symbolTable, name);
-    if (func) {
-      if constexpr (std::is_same_v<T, Fortran::lower::CalleeInterface>) {
-        mlir::FunctionType ty = genFunctionType();
-        if (!func.getBlocks().empty())
-          fir::emitFatalError(
-              func.getLoc(),
-              "conflicting procedure definition with mismatched signature");
-        if (func.getFunctionType() != ty) {
-          func.setType(ty);
-          for (const auto &placeHolder : llvm::enumerate(inputs))
-            func.setArgAttrs(placeHolder.index(),
-                             placeHolder.value().attributes);
-        }
-      }
-    }
     if (!func) {
       mlir::Location loc = side().getCalleeLocation();
       mlir::MLIRContext &mlirContext = converter.getMLIRContext();
diff --git a/flang/test/Lower/extrn_subp.f90 b/flang/test/Lower/extrn_subp.f90
new file mode 100644
index 0000000000000..c43f65a72d766
--- /dev/null
+++ b/flang/test/Lower/extrn_subp.f90
@@ -0,0 +1,30 @@
+! RUN: bbc -emit-hlfir -o - %s | FileCheck %s
+
+module m1
+  external :: sub
+  type ty
+    procedure(), pointer, nopass :: ptr5 => sub
+  end type
+  procedure(), pointer :: ptr6 => sub
+end module
+
+use m1
+integer :: jj = 4
+call ptr6(10)
+print *, "Pass"
+end
+
+subroutine sub(a)
+  integer :: a
+  print *, "sub"
+end subroutine
+
+! CHECK-LABEL: func.func @_QQmain() {
+! CHECK:         %[[PTR6_ADDR:.*]] = fir.address_of(@_QMm1Eptr6) : !fir.ref<!fir.boxproc<() -> ()>>
+! CHECK:         %[[PTR6:.*]]:2 = hlfir.declare %[[PTR6_ADDR]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QMm1Eptr6"}
+! CHECK:         %[[C10:.*]] = arith.constant 10 : i32
+! CHECK:         %[[TMP:.*]]:3 = hlfir.associate %[[C10]] {adapt.valuebyref} : (i32) -> (!fir.ref<i32>, !fir.ref<i32>, i1)
+! CHECK:         %[[P:.*]] = fir.load %[[PTR6]]#0 : !fir.ref<!fir.boxproc<() -> ()>>
+! CHECK:         %[[F:.*]] = fir.box_addr %[[P]] : (!fir.boxproc<() -> ()>) -> ((!fir.ref<i32>) -> ())
+! CHECK:         fir.call %[[F]](%[[TMP]]#0) fastmath<contract> : (!fir.ref<i32>) -> ()
+! CHECK:         hlfir.end_associate %[[TMP]]#1, %[[TMP]]#2 : !fir.ref<i32>, i1
\ No newline at end of file
diff --git a/flang/test/Semantics/extrn_subp.f90 b/flang/test/Semantics/extrn_subp.f90
index 5336daf22d248..2624fa4cb3a90 100644
--- a/flang/test/Semantics/extrn_subp.f90
+++ b/flang/test/Semantics/extrn_subp.f90
@@ -17,4 +17,4 @@ Module m1
 subroutine sub(a)
   integer::a
   print*,"sub"
-end subroutine
\ No newline at end of file
+end subroutine



More information about the flang-commits mailing list